问题
I am trying to add a couple of JButton objects to my GUI program in Java and it is adding them to the JPanel (which is the main file of the program) but it is appearing in the incorrect spot. It is showing op at point [0, 0] and the action that is linked to it is happening at the correct spot. The rest of the elements on the panel are Images so the repaint method is called very often.
private void init()
{
setLayout(null);
setBackground(new Color(r, g, b));
addMouseListener(this);
addMouseMotionListener(this);
setSize(681, 700);
setPreferredSize(new Dimension(681, 700));
Insets insets = getInsets();
//wrong spot (click at [302, 5])
undoButton = new JButton("Undo");
undoButton.addActionListener(this); //button 1
undoButton.setActionCommand("undo");
undoButton.setVisible(true);
add(undoButton);
pause = new JButton("pause");
pause.addActionListener(this);
pause.setActionCommand("pause"); //button 2
pause.setVisible(true);
pause.setEnabled(true);
add(pause);
Dimension size = undoButton.getPreferredSize();
undoButton.setBounds(100 + insets.left, 15 + insets.top, size.width, size.height);
size = pause.getPreferredSize();
pause.setBounds(100 + insets.left + undoButton.getPreferredSize().width, 15 + insets.top, size.width, size.height);
try{
undoButton.setMultiClickThreshhold(500);
}
catch (Exception e)
{}
//... more code ...
}
public void paint (Graphics g)
{
//...paint the rest of the elements...
undoButton.update(g);
pause.update(g);
}
The "pause" button is showing up at the origin on top of the undo button but the clicks is woking at the correct spots. The 2 buttons should be showing up where the blue box is and all of the other cards are Images.
回答1:
You should not be overriding paint
, you should be overriding paintComponent
. If your components have already been added to the panel, they will update themselves:
public void paintComponent(Graphics g)
{
super.paintComponent(g);
//...paint the rest of the elements...
//undoButton.update(g); BAD!
//pause.update(g); BAD!
}
You don't have to worry about how the buttons get updated, the panel will handle that for you if you use it properly. Also do not use setLayout(null)
. We have layout managers for a reason, use one that has the features you need or write your own.
回答2:
Because there are components that are moved around and need to be repainted very often
I see absolutely no reason to ever move the "Undo" and "Pause" buttons. These buttons should be added to a panel with uses a Flow Layout. Then add the panel to the NORTH of the frame.
Get rid of the null layout.
Get rid of the setPreferredSize() statements. The layout manager will determine the size of the buttons.
So I needed to override paint().
You should never override the paint() method of a JFrame. The default implementation of this method is responsible for painting the components that have been added to the frame.
Read the section from the Swing tutorial on How to Use Buttons for working examples and a better way to structure your code.
Edit:
You should NOT override paint() on the frame.
If you want to do custom painting you override paintComponent(...)
of a JPanel
and add the panel to the frame.
If you want to add some buttons to this panel then you could do something like:
JPanel buttonPanel = new JPanel();
buttonPanel.add(undoButton);
buttonPanel.add(pauseButton);
buttonPanel.setSize( buttonPanel.getPreferredSize() );
buttonPanel.setLocation(100, 0);
paintingPanel.add( buttonPanel );
来源:https://stackoverflow.com/questions/29782303/jbutton-showing-up-in-the-wrong-spot-after-repaint-is-called