Announcement

Collapse
No announcement yet.

Verständnis- und Programmierfrage in Bezug auf swing

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Verständnis- und Programmierfrage in Bezug auf swing

    Ich bin gerade dabei, eine grafische Oberfläche in swing zu programmieren. Es handelt sich um eine einfach Oberfläche, diese hat einen Butten namens "choose", wird dieser gedrückt, dann öffnet sich ein FileChooser, mit der man Bilddateien öffnen kann. Wenn man doch kein Bild öffnen will, dann soll eben die ursprüngliche Oberfläche mit ihren Knöpfen hergestellt werden. Dies passiert manchmal - manchmal aber auch nicht, ein Fehler, den ich als Threadproblem identifiziert habe, aber nicht lösen konnte. Hier die Mainmethode...


    Code:
     	public static void main(String[] args) {
    		
    		   MainFrame m = new MainFrame();		 
    		   m.showGUI();
    		   
    	}
    So so sieht die showGUI-Methode aus:

    Code:
    public void showGUI() {
    		
    	setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
           
    	scalingImage();
    	
    	graphicDesign();
    	         
    	}
    scalingImage(); ist dafür zuständig, das Bild zu skalieren, wenn es zu groß ist - das Problem liegt in graphicDesign(); Dort wird die GUI zusammengesetzt, und es gibt Buttons, die ActionListenr haben:

    Code:
    private void graphicDesign() {
    		iconBox = Box.createHorizontalBox(); 
    		
    			imgicon = new JLabel(imageinfo.getimageIcon());
    			
    		iconBox.add(imgicon); 
    		
    		GridLayout grButtonPane = new GridLayout(2,0);
    		buttonPane = new JPanel();
    		buttonPane.setLayout(grButtonPane);
    		
    				btnChoose = new Button("choose");     		 
    				btnChoose.addActionListener(this);
    				
    				btnCancel = new Button("cancel");
    				btnCancel.addActionListener(this);	 
    			
    		  FlowLayout flButtonPane = new FlowLayout();
    		 
    		  buttons = new JPanel();
    		  buttons.setLayout(flButtonPane);
    		  buttons.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); 
    		  buttons.add(btnChoose);
    		  buttons.add(btnCancel);
    		  
    		  		btnPrevious = new Button("previous");
    		  		btnNext = new Button("next");
    		  		btnRotate = new Button("rotate");
    		  
    		  
    		  changebuttons = new JPanel();
    		  changebuttons.setLayout(flButtonPane);
    		  changebuttons.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
    		  changebuttons.add(btnPrevious);
    		  changebuttons.add(btnNext);
    		  changebuttons.add(btnRotate);
    		 	
    		buttonPane.add(buttons);
    		buttonPane.add(changebuttons);
    		
        add(iconBox); 
        add(buttonPane);
    	}
    Wenn nun ein Actionevent fliegt, dann ist hier der ActionListener:

    Code:
    	@Override
    	public void actionPerformed(ActionEvent ae) {
    		
    		
    	 if(ae.getSource()== btnChoose){
    		 
     		 defaultLoader = new Loader();
    		 
    		 selectedF = defaultLoader.initialize();
    	 	 
    		 		imageIcon = new ImageIcon(selectedF);
    		 		imageinfo.setNewData(imageIcon);
    		 		
    		 		 
    	 }else if(ae.getSource()== btnCancel){
    	
    	    System.exit(0);
    		 
    	 }
    		
    
    	t = new Thread() {
    	      public void run() {
    		        clear();
    		      }
    
    		private void clear() {
    			
    	         getContentPane().remove(iconBox);
           		  getContentPane().remove(buttonPane);
           		  revalidate();
           		  repaint();
           		  update();
    			
    		}
    
    		private void update() {
    			  SwingUtilities.invokeLater(new Runnable() {
    				    public void run() {
    				       showGUI();
    				    }
    				  });
    
    
    			
    		}
    		    };
    	t.start();
    	 	 
    	}
    Ich verstehe Folgendes nicht. Wieso schafft es der Einsatz von SwingUtilities.invokeLater nicht, dafür zu sorgen, dass erst dies:

    Code:
    getContentPane().remove(iconBox);
           		  getContentPane().remove(buttonPane);
           		  revalidate();
           		  repaint();
           		  update();
    ... und dann erst showGUI ausgeführt wird, sodass ich, wenn ich den FileChoser öffne und dann aber auf abbrechen gehe, wieder die ursprüngliche Oberfläche mit allen Buttons zu sehen ist. Den Code habe ich mal anbei als Anhang hochgeladen.
    Attached Files

  • #2
    Warum ein Thread um einen Filechooser anzuzeigen?

    Des weiteren kein Thread benutzen, sondern einen SwingWorker mit publish und process
    Christian

    Comment


    • #3
      Das habe ich gerade versucht, jund dabei festetsllen müssen, dass es sich bei dem Problem offenbar gar nicht um ein Threadproblem handelt. Die Eventlistener-methode sieht bei mir nun so aus:

      Code:
      	@Override
      	public void actionPerformed(ActionEvent ae) {
      		
      	 if(ae.getSource()== btnChoose){
      		 
       		 defaultLoader = new Loader();
      		 
      		 selectedF = defaultLoader.initialize();
      	 	 
      		 		imageIcon = new ImageIcon(selectedF);
      		 		imageinfo.setNewData(imageIcon);
      		 		
      		 		 
      	 }else if(ae.getSource()== btnCancel){
      	
      	    System.exit(0);
      		 
      	 }
      
          
      	RefurbishSwingWorker ref = new RefurbishSwingWorker(this, iconBox, buttonPane);
      	ref.execute();
      		 
      	
      	}
      Durch die publish()-Methode des Swingworkers habe ich festgestellt, dass revalidate(), repaint() sowie der erneute Aufruf von showGUI() immer schön in der richtigen Reihenfolge geschehen. Dennoch ist es so, dass ich immer, wenn ich beim Filechooser kein Bild auswähle, sondern auf Abbrechen gehe, eine graues JFrame erscheint, und erst wenn ich es ein bisschen in seiner Größe verändere, bekomme ich wieder dessen Anfangszustand.

      Hier mein SwingWorker:

      Code:
      package core;
      
      
      
      import java.util.List;
      
      import javax.swing.Box;
      import javax.swing.JPanel;
      import javax.swing.SwingWorker;
      
      public class RefurbishSwingWorker extends SwingWorker<Integer,String>{
      
      	private MainFrame mf;
      	private Box iconBox;
      	private JPanel buttonPane;
      	
      public RefurbishSwingWorker(MainFrame m, Box ib, JPanel bp){
      		
      		mf = m;
      		iconBox = ib;
      		buttonPane = bp;
      	}
       
      	@Override
      	protected Integer doInBackground() throws Exception {
      		
      		publish("Removing iconBox...");
      		mf.getContentPane().remove(iconBox);
      		
      		publish("Removing buttonPane...");
      		mf.getContentPane().remove(buttonPane);
      		
      		publish("Revalidate...");
      		mf.revalidate();
      		
      		publish("Repainting...");
      		mf.repaint();
      		
      		publish("Showing GUI...");
      		mf.showGUI();
      		
      		publish("Complete");
      		
      		return 1;
      	}
      
      	@Override
      	  protected void process(final List<String> chunks) {
      	    
      	    for (final String string : chunks) {
      	      System.out.println(string);
      	    }
      	  }
      
      }
      Ich hoffe, es ist nicht zu dreist, dass ich hier derart noobige Fragen stelle, aber falls dies ein simples und allgemein bekanntes Problem ist, kann mir ja eventuell jemand einen Tipp geben.

      Comment


      • #4
        Setze das Image in einen JLabel als Icon ohne Text. Packe das Label anstatt der Box in den Frame
        Christian

        Comment


        • #5
          Ich hab's - ich habe vergessen, am Ende der showGUI-Methode pack() aufzurufen *peinlich*.

          Comment


          • #6
            Es gibt noch eine Sache, die ich nicht verstehe. Ich habe in dem Bildbearbeitungsprogramm, das ich gerade schreibe, ein ImageInfo-Objekt, wo ich alle notwendigen Infos des aktullen Bildes, das ich mir über einen Filechooser geladen habe, speichere.

            Folgende Daten des ImageIcons speichere ich in dem ImageInfo-Objekt:

            Code:
            public void setNewData(ImageIcon newImageIcon) {
            		
            		imageIcon = newImageIcon;
            		setWidth(imageIcon.getIconWidth());
            		setHeight(imageIcon.getIconHeight());
            		setCurrentpic(imageIcon.getDescription());
            		deflt=false;
            		
            	}

            Wenn ich nun von einer anderen klasse aus auf das ImageInfo-Objekt später zugreife, um herauszufinden, in welchem Verzeichnis sich das Bild befindet...

            Code:
            public String getCurrentImageDirectory() {
            		 
            		 String dir = imageIcon.getDescription().substring(0,imageIcon.getDescription().lastIndexOf("/"));
            		 
            			return dir;
            		}
            ...passert folgendes:

            Bei einigen Bildern bekomme ich bei imageIcon.getDescription() eine Nullpointer-Exception, bei anderen Bildern nicht.

            Wie kann dies sein? Hat jemand Erfahrung mit der getDescription()-Methode der JAVA-Klasse "ImageIcon"?

            Comment


            • #7
              Schon mal in die Doku geschaut

              https://docs.oracle.com/javase/7/doc...ImageIcon.html


              ....The description may be null.
              Christian

              Comment


              • #8
                Danke, ich habe es jetzt behoben.

                Comment


                • #9
                  Code:
                  import java.awt.Button;
                  import java.awt.ComponentOrientation;
                  import java.awt.Dimension;
                  import java.awt.FlowLayout;
                  import java.awt.Graphics2D;
                  import java.awt.GridLayout;
                  import java.awt.Image;
                  import java.awt.Point;
                  import java.awt.event.ActionEvent;
                  import java.awt.event.ActionListener;
                  import java.awt.image.BufferedImage;
                  import java.io.File;
                  
                  import javax.swing.Box;
                  import javax.swing.BoxLayout;
                  import javax.swing.ImageIcon;
                  import javax.swing.JFrame;
                  import javax.swing.JLabel;
                  import javax.swing.JPanel;
                   
                  
                  public class Main extends JFrame implements ActionListener{	
                   	
                  	private ImageIcon myicon;
                  	private Box iconBox;
                  	private JLabel imgicon;
                  	private JPanel buttonPane;
                  	private JPanel buttons;
                  	private Button btnRotate;
                  	
                  	public Main(){
                  		setVisible(true);
                  		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                  		setMinimumSize(new Dimension(500,500));
                  	}
                  	
                  	
                  	private void graphicDesign() {
                  		
                  		iconBox = Box.createHorizontalBox(); 
                  		
                  	
                  	myicon = new ImageIcon(("/home/user/Schreibtisch/df.jpg"));
                  	imgicon = new JLabel(myicon);
                  		
                  	iconBox.add(imgicon); 
                  	
                  	GridLayout grButtonPane = new GridLayout(2,0);
                  	buttonPane = new JPanel();
                  	buttonPane.setLayout(grButtonPane);
                  	 
                  			btnRotate = new Button("rotate");     		 
                  			btnRotate.addActionListener(this);
                  	 
                  		
                  	  FlowLayout flButtonPane = new FlowLayout();
                  	 
                  	  buttons = new JPanel();
                  	  buttons.setLayout(flButtonPane);
                  	  buttons.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); 
                  	  buttons.add(btnRotate);
                  	
                      buttonPane.add(buttons);
                  	
                  
                  add(iconBox); 
                  add(Box.createVerticalGlue());
                  add(buttonPane);
                  pack();
                  		
                  	}
                  	
                  	public static BufferedImage convertToBufferedImage(Image image)
                  	{
                  	    BufferedImage newImage = new BufferedImage(
                  	        image.getWidth(null), image.getHeight(null),
                  	        BufferedImage.TYPE_INT_ARGB);
                  	    Graphics2D g = newImage.createGraphics();
                  	    g.drawImage(image, 0, 0, null);
                  	    g.dispose();
                  	    return newImage;
                  	}
                  	
                  	private void showGUI() {
                  		
                  		setLayout(new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS));
                     		
                  		graphicDesign();
                  		
                  	}
                  	
                  
                  	@Override
                  	public void actionPerformed(ActionEvent ae) {
                  		
                  		if(ae.getSource()== btnRotate){
                  		
                  			 
                  		 	
                  			BufferedImage bi = convertToBufferedImage(myicon.getImage());
                  			 Graphics2D graphics2D = bi.createGraphics();
                  			
                  			
                  			 Point p = iconBox.getLocation();
                  			 Dimension d = iconBox.getSize();
                  	         
                                  double x = p.x+d.height/2;
                  	        double y = p.y+d.width/2;
                  	       
                                 //System.out.println( x + "  " + y);
                  	        
                                   graphics2D.rotate(Math.toRadians(90), x, y);
                  	         graphics2D.drawImage(bi, p.x, p.y,null);
                  	         graphics2D.dispose();
                  	         
                  		}	 
                  		
                  	}
                  
                  	
                  	public static void main(String[] args) {
                  		
                  		   Main m = new Main();		 
                  		   m.showGUI();
                  		   
                  	}
                  
                  	
                  }
                  Ich habe noch eine Frage in Bezug auf die Frage, wie man ein Bild rotieren lassen kann. Ich habe ein einfaches JFrame erstellt und ein Bild sowie einen Knopf auf dieses platziert - siehe die showGUI()-Methode, das GUI-Gerüst wird in der graphicDesign()-Methode erstellt.

                  Nun will ich das Bild rotieren lassen, sobald der rotate-Button gedrückt wird (siehe implementierte Methode des Actionlistener).

                  Ich verstehe nur nicht, was daran falsch ist, d. h. wieso dies nicht funktioniert.

                  Hier die Refurbisher-Klasse:

                  Code:
                  import java.awt.Component;
                  import java.util.List;
                  
                  import javax.swing.Box;
                  import javax.swing.JPanel;
                  import javax.swing.SwingWorker;
                  
                  public class Refurbisher extends SwingWorker<Integer,String>{
                  
                  	private Main mf;
                  	private Box iconBox;
                  	private JPanel buttonPane;
                  	private Component rigidAreaUpper,rigidAreaMiddle, rigidAreaLower;
                  	
                    public Refurbisher(Main m, Box ib, JPanel bp){
                  		
                  		mf = m;
                  		iconBox = ib;
                  		buttonPane = bp;
                  	 
                  		
                  		
                  	}
                   
                  	@Override
                  	protected Integer doInBackground() throws Exception {
                  		
                  		mf.getContentPane().remove(rigidAreaUpper);
                  		
                  		mf.getContentPane().remove(rigidAreaMiddle);
                  		
                  		//publish("Removing iconBox...");
                  		mf.getContentPane().remove(iconBox);
                  		
                  		//publish("Removing buttonPane...");
                  		mf.getContentPane().remove(buttonPane);
                  
                  		mf.getContentPane().remove(rigidAreaLower);
                  		
                  		//publish("Revalidate...");
                  		mf.revalidate();
                  		
                  		//publish("Repainting...");
                  		mf.repaint();
                  		
                  		//publish("Showing GUI...");
                  		mf.showGUI();
                  		
                  		//publish("Complete");
                  		
                  		return 1;
                  	}
                  
                  	@Override
                  	  protected void process(final List<String> chunks) {
                  	    
                  	    for (final String string : chunks) {
                  	      //System.out.println(string);
                  	    }
                  	  }
                  
                  }

                  Comment


                  • #10
                    wieso dies nicht funktioniert.
                    Ist kein Fehler. Was funktioniert nicht?

                    [highlight=java]
                    public static BufferedImage rotateLeft(BufferedImage img)
                    {
                    int width=img.getWidth();
                    int height=img.getHeight();
                    BufferedImage result=new BufferedImage(height,width,BufferedImage.TYPE_INT_ RGB);
                    for(int x=0;x<width;x++)
                    {
                    for(int y=0;y<height;y++)
                    {
                    result.setRGB(y,width-x-1,img.getRGB(x,y));
                    }
                    }
                    return result;
                    }

                    public static BufferedImage rotateRight(BufferedImage img)
                    {
                    int width=img.getWidth();
                    int height=img.getHeight();
                    BufferedImage result=new BufferedImage(height,width,BufferedImage.TYPE_INT_ RGB);
                    for(int x=0;x<width;x++)
                    {
                    for(int y=0;y<height;y++)
                    {
                    result.setRGB(height-y-1,x,img.getRGB(x,y));
                    }
                    }
                    return result;
                    }

                    public static BufferedImage rotate(BufferedImage img,double degrees)
                    {
                    Dimension d=berechneNeueGroesse(degrees,img.getWidth(),img.g etHeight());
                    int m=Math.max(d.width,d.height);
                    BufferedImage rotateImg=new BufferedImage(m,m,BufferedImage.TYPE_INT_ARGB);
                    int x=(m-img.getWidth())/2;
                    int y=(m-img.getHeight())/2;
                    rotateImg.getGraphics().drawImage(img,x,y,null);
                    AffineTransform transform=new AffineTransform();
                    transform.rotate(Math.toRadians(degrees),m/2,m/2);
                    AffineTransformOp op=new AffineTransformOp(transform,AffineTransformOp.TYPE _BILINEAR);
                    return op.filter(rotateImg,null);

                    }

                    private static Dimension berechneNeueGroesse(double degrees,int width,int height)
                    {
                    double widthA=Math.abs(Math.cos(degrees)*width);
                    double widthB=Math.abs(Math.sin(degrees)*width);
                    double heightA=Math.abs(Math.cos(degrees)*height);
                    double heightB=Math.abs(Math.sin(degrees)*height);
                    return new Dimension((int)(widthA+heightB),(int)(widthB+heigh tA));
                    }


                    [/highlight]
                    Christian

                    Comment


                    • #11
                      Naja, so wie ich es geschrieben hatte, konnte ich das Bild nicht drehen. So wie oben angegeben funktioniert es nun aber; ich werde diesen Code aufmerksam durchgehen, dass ich was lernen kann. Und vielen vielen Dank für die große Hilfe.

                      Comment


                      • #12
                        Es wäre schön für jede Frage einen neuen Thread zu öffnen sind ja doch einige Thema hier drin. Nur so fürs nächste mal

                        Comment

                        Working...
                        X