Thy Gamosh
Thy Gamosh

Reputation: 77

Why JFrame fails to display when thread is invoked?

(I've seen the other 2 questions that are similar to mine in title, but they are different and do not provide a solution to my problem.)

Hi,

I have the below code of simple display of lines. I'm declaring a JFrame in the main, then calling on a new instance of the DrawGraph1 class, passing the JFrame as argument. In the constructor, I'm invoking a thread (EventQueue.invokeLater). The constructor use the JFrame and use it to create some lines and string and whatever)

(Sorry about improper indentation, it has been tweaked a lot)

package test;
import java.awt.*;
import java.awt.geom.*;
import java.text.DateFormatSymbols;
import javax.swing.*;

public class test {
   public static void main(String[] args){                 
       final JFrame frame = new JFrame();   

       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       frame.setSize(800, 700);
       frame.setVisible(true);  
       DrawGraph1 obj = new DrawGraph1(frame);
}
}
class DrawGraph1{        
    DrawGraph1(final JFrame frame){
        EventQueue.invokeLater(new Runnable(){            
        @Override               
        public void run(){                 
       frame.setTitle("LineDrawing");     
        frame.add(new JComponent()
            {
               @Override
               public void paintComponent(Graphics g)
               {
                  Graphics2D g2 = (Graphics2D) g;
                  Line2D line = new Line2D.Double();
                  int decrement = 0, label = 0;                  

                  g2.setColor(Color.red);          
                  g.drawString("Red Line ->> High temperatures", 330, 110);
                  g2.setColor(Color.green);          
                  g.drawString("Green Line ->> Low temperatures", 330, 130);
                  } });}});}}

So According to my testing, the program reaches the constructor, passes the frame, and starts the thread, but apparently it stops at the line

frame.add(new JComponent()

With the NetBeans debugger underlining (or something) the add method. I also tried in which I invoke the thread at the main, pass the JFrame to the constructor, jump to it and it also stops at the same statement.

The display is simply the Frame itself with whatever settings prior to the add statement (i.e. in the main settings such as size).

I'm pretty sure it is very silly problem since it worked yesterday, not sure what I changed, but I just gave up.

Upvotes: 0

Views: 93

Answers (2)

Gilbert Le Blanc
Gilbert Le Blanc

Reputation: 51445

Primarily, you passed the JFrame to the JPanel. You should create the JPanel, and pass it to the JFrame.

Here are the major changes I made.

  1. All of the Swing GUI creation has to be on the Event Dispatch Thread. This includes the JFrame and the JPanel. I added a Runnable to the main method, and called the EventQueue invokeLater method to start the Swing GUI on the Event Dispatch Thread.

  2. I moved all the JFrame code in the main method, and all of the JPanel drawing code in the DrawGraph1 class paintComponent method. The paintComponent method is for painting only. Do your other processing in other classes and / or other methods.

  3. The JFrame methods have to be called in a specific order. Call the JFrame methods in the same order that I called them in your code.

  4. I added a call to super.paintComponent to your paintComponent method. This maintains the Swing paint chain and clears the drawing panel.

  5. I moved the sizing of the GUI from the JFrame to the JPanel. You're concerned with the size of the drawing panel, not the entire GUI.

Here's the revised code. I renamed the class so that it wouldn't conflict with other code in my testing package. You should change it back.

package com.ggl.testing;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class SimpleJPanelTest {

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                final JFrame frame = new JFrame("Line Drawing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                frame.add(new DrawGraph1());
                frame.pack();
                frame.setLocationByPlatform(true);
                frame.setVisible(true);
            }
        };
        EventQueue.invokeLater(runnable);
    }
}

class DrawGraph1 extends JPanel {

    private static final long serialVersionUID = 6733473371292195071L;

    public DrawGraph1() {
        setPreferredSize(new Dimension(800, 700));
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D) g;
        Line2D line = new Line2D.Double();
        int decrement = 0, label = 0;

        g2.setColor(Color.red);
        g.drawString("Red Line ->> High temperatures", 330, 110);
        g2.setColor(Color.green);
        g.drawString("Green Line ->> Low temperatures", 330, 130);
    }

}

Upvotes: 1

Jorge Nieto
Jorge Nieto

Reputation: 119

I just changed the order of these two lines.

frame.setVisible(true);
DrawGraph1 obj = new DrawGraph1(frame);

to

DrawGraph1 obj = new DrawGraph1(frame);
frame.setVisible(true);

and the output:

Output

Upvotes: 1

Related Questions