JLabel paints new text over the old one, after set text is called
I have a progress dialog window, which contains 3 JComponents: JLabel, JProgressBar, JButton, which is used as default dialog window in different parts of the application from different threads. So when i try to change the value of the label, it does not clear the background under it, it just paints new text over the old one. The wrapper class does not override any methods it just delegate method calls to components it contains.
Here is code:
public void setNote(String note) {
this.note = note;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
label.setText(ProgressDialog.this.note);
}
});
}
The actual result is similar to http://www.daniweb.com/forums/post1073367.html#post1073367 But that solution was not appropriate for me.
Has anyone faced problem like this?
Thanks.
This is cuted version of the class. But as I said i could not make it work incorrectly. Hope this helps.
public class Tesssst {
public static void main(String [] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ProgressDialog dialog = new ProgressDialog(frame, "Title", "Message");
dialog.showDialog(true);
}
}
class ProgressDialog extends JComponent {
/**
*
*/
private JProgressBar progressBar;
private JLabel label;
private JFrame parentComponent;
private String title;
private String note;
private boolean canceled;
private boolean cancelEnabled;
private JButton btnCancel;
private JPanel contentPanel;
public ProgressDialog(JFrame parentComponent, String title, String message) {
this.parentComponent = parentComponent;
this.title = title;
progressBar = new JProgressBar();
label = new JLabel();
contentPanel =new JPanel();
canceled = false;
cancelEnabled = true;
setNote(message);
setOpaque(true);
}
public void setNote(String note) {
this.note = note;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
label.setText(ProgressDialog.this.note);
}
});
}
public String getNote() {
return note;
}
protected void initDialog() {
setBorder(new EmptyBorder(6, 6, 6, 6));
contentPanel = new JPanel();
contentPanel.setOpaque(true);
setLayout(new BorderLayout());
add(contentPanel);
btnCancel = new JButton("Cancel");
btnCancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
label.setText("ololo");
}
});
contentPanel.setLayout(new GridBagLayout());
{
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.NONE;
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.insets = new Insets(2, 0, 0, 0);
label.setOpaque(true);
contentPanel.add(label, gbc);
} // label
{
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.NORTH;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(4, 0, 4, 0);
contentPanel.add(progressBar, gbc);
} // progressBar
{
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 2;
gbc.anchor = GridBagConstraints.NORTH;
gbc.fill = GridBagConstraints.NONE;
gbc.insets = new Insets(4, 0, 4, 0);
contentPanel.add(btnCancel, gbc);
btnCancel.setEnabled(cancelEnabled);
} // cancel*/
} // funciton
public boolean isCanceled() {
return canceled;
}
public void showDialog() {
showDialog(false);
}
public void showDialog(bo开发者_如何学运维olean modal) {
JDialog dialog = new JDialog(parentComponent, true);
initDialog();
dialog.getContentPane().add(contentPanel);
dialog.setSize(400,400);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
if (modal) {
dialog.setAlwaysOnTop(true);
}
dialog.setVisible(true);
dialog.toFront();
}
public void cancel() {
canceled = true;
}
}
Try setOpaque(true)
on the Label, this should cause it to clear its background.
try perhaps a repaint()
on the adequate component after setting the text.
Try extending JPanel instead of JComponent.
JComponent does not have any code to paint its background. So making the component opaque doesn't do anything to wipe out the old text. Keep the label non-opaque and use an opaque JPanel as the container of your component.
Maybe you are using backgrounds with an alpha value somewhere. If so you can check out Background With Transparency for some problems you might encounter.
Otherwise only you can compare your working code with the non-working code to see what is different.
The problem was with opacity. In our default look and feel "Panel.background" property was set to new Color(135, 15, 19, 0)
. So all panels were by default non-opaque. The label called repaint()
method and as all parent panels were non-opaque the background refresh was not performed.
Thanks everyone for you replies.
The answer from camickr is the right way to proceed; however one thing clearly wrong with your test is your swing thread usage.
I suspect that it may also have something to do with it being a dialog. Dialogs typically block the SWMET in the call to showDialog(); thus, a second event thread is usually created in showDialog(). Here you are not calling showDialog() from a the SWMET you are calling it from main -- maybe you are seeing some strange effects of that.
public static void main(String args[]) throws Exception {
SwingUtils.invokeLater(new Runnable() {
public void run() {
ProgressDialog dialog = new ProgressDialog(frame, "Title", "Message");
dialog.showDialog(true);
}
});
}
You need to put super.paintComponent(g);
精彩评论