Refreshing Swing Frage

js2002

Mitglied
Hi,

ich hab mich mit Swing und Threads befasst und dashier gefunden.

Java digital clock

1. Für das Starten soll das besser sein, verstanden hab ich es nicht? anyone?

Code:
SwingUtilities.invokeLater(new Clock());

2. Das JFrame implementiert Runnable ist also gethreadet.
Jetzt dachte ich: hm, jetzt kann ich ja gar nicht andere Panels einbauen, die nicht refresht werden müssen, weil die ja auch ständig "repainted" werden. Das ist ja resourcendfressend usw. Jetzt hab ich aber bestgestellt, das es problemlos geht und die anderen Panels gar nicht refresht werden. Kann das jem erklären?
Ist die repaint Methode so definiert, dass sie nur die Panels mit
Code:
 public void paintComponent(Graphics painter )
Methode aufruft?!

Java:
import java.awt.*;
import javax.swing.*;       
import java.util.*;

class Clock extends JFrame implements Runnable
{
  Thread runner; //declare global objects
  Font clockFont;
 
     public Clock()
     {
       super("Java clock");
       setSize( 350, 100);
       setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       setVisible(true);
       setResizable(false);                             //create window
   
       clockFont = new Font("Serif", Font.BOLD, 40);    //create font instance
       
       Container contentArea = getContentPane();
       ClockPanel timeDisplay = new ClockPanel();

 
       contentArea.add(timeDisplay);                    //add components
       setContentPane(contentArea);
       start();                                         //start thread running
     
     }
     
     
     class ClockPanel extends JPanel
     {
      public void paintComponent(Graphics painter )
        {
        Image pic =
          Toolkit.getDefaultToolkit().getImage("background.jpg");
         
         if(pic != null)
           
            painter.drawImage(pic, 0, 0, this);     //create image
     
                 
//if I didn't use a background image I would have used the setColor and fillRect methods to set background
     
          painter.setFont(clockFont);                   //create clock components
          painter.setColor(Color.black);
          painter.drawString( timeNow(), 60, 40);
         
   
        }
     }

     
     //get current time
     public String timeNow()
     {
       Calendar now = Calendar.getInstance();
       int hrs = now.get(Calendar.HOUR_OF_DAY);
       int min = now.get(Calendar.MINUTE);
       int sec = now.get(Calendar.SECOND);
       
       String time = zero(hrs)+":"+zero(min)+":"+zero(sec);
       
       return time;
     }


     
     public String zero(int num)
     {
       String number=( num < 10) ? ("0"+num) : (""+num);
       return number;                                    //Add leading zero if needed
       
     }
     
     
     public void start()
     {
       if(runner == null) runner = new Thread(this);
       runner.start();
                                                             //method to start thread
     }


     public void run()
     {
       while (runner == Thread.currentThread() )
       {
        repaint();
                                                         //define thread task
           try
             {
               Thread.sleep(1000);
             }
              catch(InterruptedException e)
                  {
                    System.out.println("Thread failed");
                  }
                 
       }
     }
     
     //create main method
     public static void main(String [] args)
     {
       Clock eg = new Clock();
     }
}
 
Du brauchst gar keinen Thread, nur einen Timer.
Ist die repaint Methode so definiert, dass sie nur die Panels mit public void paintComponent(Graphics painter ) Methode aufruft?!
Nein, ist sie nicht. Zum Thema resourcen, du solltest nicht repaint auf dem Frame aufrufen, sondern nur auf dem Teil der sich ändert, also ClockPanel (auch wenn das in deinem Fall praktisch aufs Gleiche rauskommt).
 
Also so ist dann falsch?
Jetzt hab ich mehr Panels drin, ich hoffe du steisgst noch durch.

Java:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;       
import java.util.*;

class Hauptfenster extends JFrame implements Runnable, ActionListener 
{
  Thread runner; //declare global objects
  Font clockFont;
  Font inputFont = new Font("Serif", Font.BOLD, 20);
 
     public Hauptfenster()
     {
       super("Chefsache Timer v0.1 2011");
       //setLocationRelativeTo(null);
       GridLayout layout = new GridLayout(2,2,10,10);
       setLayout(layout);
       /*
   	add(new JButton("Button 1"));
	add(new JButton("Button 2"));
	add(new JButton("Button 3"));
	add(new JButton("Long-Named Button 4"));
	add(new JButton("5"));
       */
       setSize( 500, 300);
       setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       setVisible(true);
       setResizable(false);                             //create window
   
       clockFont = new Font("Serif", Font.BOLD, 40);    //create font instance

       Container contentArea = getContentPane();
       ClockPanel timeDisplay = new ClockPanel();

       contentArea.add(timeDisplay);                    //add components
       contentArea.setBackground(Color.white);
       
       JPanel leer = new JPanel();
       leer.setBackground(Color.white);
       
       JPanel eingabepanel = new JPanel();
       
       Calendar jetzt = Calendar.getInstance();
       
       int tag = jetzt.get(Calendar.DAY_OF_MONTH);
       int monat = jetzt.get(Calendar.MONTH);
       int jahr = jetzt.get(Calendar.YEAR);
       
       String datum = String.valueOf(tag) + "." + String.valueOf(monat) + "." + String.valueOf(jahr); 
       
       JTextField iDatum = new JTextField(datum, 10);
       iDatum.setFont(inputFont);
       iDatum.setHorizontalAlignment(JTextField.CENTER);
       JTextField iStunde = new JTextField(10);
       iStunde.setFont(inputFont);
       iStunde.setHorizontalAlignment(JTextField.CENTER);
       JTextField iMinute = new JTextField(10);
       iMinute.setFont(inputFont);
       iMinute.setHorizontalAlignment(JTextField.CENTER);
       
       eingabepanel.add(new JLabel("Datum"));
       eingabepanel.add(iDatum);
       
       
       eingabepanel.add(new JLabel("Stunde"));
       eingabepanel.add(iStunde);
       eingabepanel.add(new JLabel("Minute"));
       eingabepanel.add(iMinute);
       //eingabepanel.add(new JButton("Go2!"));
       GridLayout layout2 = new GridLayout(0,2,5,5);
       eingabepanel.setLayout(layout2);
       
       contentArea.add(leer);
       contentArea.add(eingabepanel);
       JButton button = new JButton("Wecker setzen!");
       button.setSize(25, 25);
       Font buttonFont = new Font("Serif", Font.BOLD, 20);
       button.setFont(buttonFont);
       contentArea.add(button);
       
      // contentArea.add(jl,BorderLayout.WEST);                    //add components

       setContentPane(contentArea);
       start();                                         //start thread running
     
     }
     
     
     class ClockPanel extends JPanel
     {
      public void paintComponent(Graphics painter )
        {
        Image pic =
          Toolkit.getDefaultToolkit().getImage("backgroundx.jpg");
         
         if(pic != null)
           
            painter.drawImage(pic, 0, 0, this);     //create image
     
                 
//if I didn't use a background image I would have used the setColor and fillRect methods to set background
     
          painter.setFont(clockFont); 			//create clock components
          painter.setColor(Color.black);
          painter.drawString( timeNow(), 50, 80);
         
   
        }
     }

     
     //get current time
     public String timeNow()
     {
       Calendar now = Calendar.getInstance();
       int hrs = now.get(Calendar.HOUR_OF_DAY);
       int min = now.get(Calendar.MINUTE);
       int sec = now.get(Calendar.SECOND);
       
       String time = zero(hrs)+":"+zero(min)+":"+zero(sec);
       
       return time;
     }


     
     public String zero(int num)
     {
       String number=( num < 10) ? ("0"+num) : (""+num);
       return number;                                    //Add leading zero if needed
       
     }
     
     
     public void start()
     {
       if(runner == null) runner = new Thread(this);
       runner.start();
                                                             //method to start thread
     }


     public void run()
     {
       while (runner == Thread.currentThread() )
       {
        repaint();
                                                         //define thread task
           try
             {
               Thread.sleep(1000);
             }
              catch(InterruptedException e)
                  {
                    System.out.println("Thread failed");
                  }
                 
       }
     }
     
     //create main method
     public static void main(String [] args)
     {
    	 //SwingUtilities.invokeLater(new Hauptfenster());
       Hauptfenster eg = new Hauptfenster();
     }



	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		
	}
}
 
Hi,

mein JOptionPane öffnet sich nur minimiert, wenn die App minimiert ist, wie bekomm ich den auf den Desktop?

Komme nicht ans JFrame.
 
Zuletzt bearbeitet:
Wie schon gesagt wurde: repaint() nur auf das ClockPanel aufrufen.

Ansonsten, das Hintergrundbild ausserhalb der paintComponent laden.

Ich habs wirklich versucht 🙁
Er repainted zwar die Uhr, aber alles wir xmal überschrieben. also sekunde 7 steht da und dann schreibt er sekunde 8 darüber usw...
Woran liegt das?
Hab ich Threads hier richtig benutzt?


Java:
import javax.swing.JFrame;


public class Haupt extends JFrame {

	
	Thread runner;
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		System.out.println("Programm gestartet.");
		Haupt gui = new Haupt();
		gui.setSize(500, 300);

		
		ClockPanel cp = new ClockPanel();
		
		Thread t = new Thread(cp);
		t.start();
		
		gui.getContentPane().add(cp);
		gui.setVisible(true);
	}
	




}

Java:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.util.Calendar;

import javax.swing.JPanel;


public class ClockPanel extends JPanel implements Runnable {
	
	//Thread thread;
	Font clockFont;
	  

	public ClockPanel() {
		//super();
		this.clockFont = new Font("Serif", Font.BOLD, 40);

		
	}

	@Override
	public void run() {
		
		String name;
		Thread thread = Thread.currentThread();
		name = Thread.currentThread().getName();
		System.out.println("running Thread:" + name);
		
	       
	       {
	           while (thread == Thread.currentThread() )
	    	   //while (true)
	           {
	       
	            repaint();
	           
	            System.out.println("repainted" + name);                                                 //define thread task
	               try
	                 {
	                   Thread.sleep(1000);
	                 }
	                  catch(InterruptedException e)
	                      {
	                        System.out.println("Thread failed");
	                      }
	                     
	           }
	         }
		
	}

    public void paintComponent(Graphics painter){

 
    	painter.setFont(clockFont); 			//create clock components
    	painter.setColor(Color.black);
    	painter.drawString( timeNow(), 50, 80);

    }
    
    public String timeNow()
    {
      Calendar now = Calendar.getInstance();
      int hrs = now.get(Calendar.HOUR_OF_DAY);
      int min = now.get(Calendar.MINUTE);
      int sec = now.get(Calendar.SECOND);
      
      String time = zero(hrs)+":"+zero(min)+":"+zero(sec);
      
      return time;
    }
    
    public String zero(int num)
    {
      String number=( num < 10) ? ("0"+num) : (""+num);
      return number;                                    //Add leading zero if needed
      
    }
 
	
}
 
Zuletzt bearbeitet:
habs, da fehlte ein super.paintComponent(painter);

aber warum?

Wird damit dem Frame gesagt, dass es auch neuzeichen muss?
Dann hätte ich ja keine Leistung gewonnen.
 
was stellst du dir denn vor, was passieren muss, damit nicht übereinander gemalt wird?
wenn du glaubst, dass dafür dass JFrame neugezeichnet werden muss, dann ist doch gut dass es passiert,
was nützt Leistungsgewinn wenn dadurch alles kreuz und quer gezeichnet wird?

tatsächlich dürfte sich super.paintComponent(painter); vor allem um genau das kümmern was minimal nötig ist:
die Zeichenfläche des JPanels löschen, ein großes Rechteck mit der Hintergrundfarbe malen,
du kannst versuchen das auch selber zu machen, dann ist super.paintComponent(painter); evtl. nicht nötig,
(falls es ein Hintergrundbild oder so gibt, wirds wohl komplizierter..)

generell ist es aber schon besser, super.paintComponent(painter); zu lassen, wer weiß was noch alles zu tun ist,
in einer Swing-GUI auf Leistung zu schauen ist ziemlich grundsätzlich ein falsche Ansatz
 
Zuletzt bearbeitet von einem Moderator:
Sinn dahinter ist nicht nur Leistung, sondern:

Ich habe ja viele andere Panels später im selben JFrame. Wenn ich in Panel xy nacher ein Combo oder Textfeld ausfülle will ich dabei ja nicht durch ein JFrame refresh gestört werden.
Oder passiert das gar nicht?
Wenn das Frame repainted wird müsste es ja andere Paneleingaben stören, das hat es aber auch schon vorher irgendwie nicht gemacht.
Kann ich irgendwie abfragen, ob das Frame repainted wurde?

2. Wie machte ich das manuelle löschen des JPanels? (ich brauch keine Bilder oder so)
 
größere Details will ich gar nicht besprechen da ich persönlich sie auch nicht weiß 😉

du könntest in super.paintComponent(painter); vertrauen,
selbst wenn es da komplizierter zugeht kennt das glaube ich Optimierungen wie Clipping, 'nur bestimmen Ausschnitt neu zeichnen'

Löschen wie gesagt Rechteck mit Hintergrundfarbe, drawRectangle,
falls du die Color brauchst schau die die Methoden des Graphics-Objekts und des JPanels an (Achtung, viele Methoden von Superklassen geerbt)
 
Zuletzt bearbeitet von einem Moderator:
//super.paintComponent(painter);

painter.setColor(Color.lightGray);
painter.fillRect(0, 0, 220, 60);

Der Code hat den super Aufruf unnötig gemacht, danke!
 

Neue Themen


Zurück
Oben