Reputation: 23
The following code appears to produce inconsistent behavior when I run it. On some runs, the canvas ends up appearing grey, but on others it end up colored blue instead. Why is this, and how can I correct it?
import java.awt.*;
import javax.swing.*;
public class psw extends JFrame {
String symbols="~ ! @ # $ % ^ & * ( ) _ = + : ; < , > . ? / | \\ '";
public static void main(String[] args){
psw app=new psw();
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) ;
app.setSize(600, 450);
app.setVisible(true);
app.getContentPane().setBackground(new Color(30,144,255));
@Override
public void paint(Graphics g) {
g.setColor(new Color(255,255,255));
g.drawRect(10, 10, 60, 50);
g.drawLine(60, 50, 220, 20);
g.drawString(symbols, 10, 150);
}
}
Upvotes: 2
Views: 249
Reputation: 209062
You need to remember to call super.paint(g);
. That shows the painting.
public void paint(Graphics g) {
super.paint(g);
g.setColor(new Color(255,255,255));
g.drawRect(10, 10, 60, 50);
g.drawLine(60, 50, 220, 20);
g.drawString(symbols, 10, 150);
}
JFrame
as they're not double buffered. Instead paint on a component, mostly JPanel
and override its paintComponent
method. Just like with paint
, you need to call super.paintComponent
. super.paintComponent(g)
invokes the paintComponent
method from the superclass of JPanel
(the JComponent
class) to erase whatever is currently drawn on the panel.Here's how it would run using a JPanel
instead of a JFrame
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class psw extends JPanel {
String symbols = "~ ! @ # $ % ^ & * ( ) _ = + : ; < , > . ? / | \\ '";
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame app = new JFrame();
app.add(new psw());
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.pack();
app.setVisible(true);
}
});
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(30, 144, 255));
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(new Color(255, 255, 255));
g.drawRect(10, 10, 60, 50);
g.drawLine(60, 50, 220, 20);
g.drawString(symbols, 10, 150);
}
public Dimension getPreferredSize() {
return new Dimension(600, 450);
}
}
Upvotes: 2
Reputation: 96434
Change your code to access the JFrame through the event dispatch thread, like this:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
The Oracle tutorial says:
Swing event handling code runs on a special thread known as the event dispatch thread. Most code that invokes Swing methods also runs on this thread. This is necessary because most Swing object methods are not "thread safe": invoking them from multiple threads risks thread interference or memory consistency errors. Some Swing component methods are labelled "thread safe" in the API specification; these can be safely invoked from any thread. All other Swing component methods must be invoked from the event dispatch thread. Programs that ignore this rule may function correctly most of the time, but are subject to unpredictable errors that are difficult to reproduce.
which sounds like what you're seeing.
Upvotes: 2