Hilfe! Java Swing

  • Themenstarter Themenstarter deddy
  • Beginndatum Beginndatum
Verstehe ich nicht, bei mir funktioniert es problemlos.

Java:
package app;

import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;

import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EtchedBorder;

public class BildWechsel implements ActionListener
{
	private static final byte WEST_BUTTON_PANEL = 0;
	private static final byte EAST_BUTTON_PANEL = 1;
	
	private static final byte BUTTON_SOURCE = 0;
	private static final byte BUTTON_DESTINATE = 1;

	private static JPanel[] buttonPanels;
	private static Icon[][] icons;
	
	private JButton pressedButton;
	
	public static void main(String[] args)
	{
		splitImage();
		setFrame();
	}
	
	private static void splitImage()
	{
		icons = new Icon[3][3];
		ImageIcon originalIcon = new ImageIcon("image.png");
		for(byte b = 0, x = 0, y = 0; b < 9; b++, x++)
		{
			BufferedImage newImage = new BufferedImage(30, 30, BufferedImage.TYPE_INT_RGB);
			Graphics g = newImage.getGraphics();
			g.drawImage(originalIcon.getImage(), x * 30 * -1, y * 30 * -1, null);
			g.dispose();
			
			icons[x][y] = new ImageIcon(newImage);
			
			if(x == 2)
			{
				x = -1;
				y++;
			}
		}
	}
	private static void setFrame()
	{
		JFrame frame = new JFrame("");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(230, 140);
		frame.setLayout(null); //TODO Eventuell FlowLayout?
		
		buttonPanels = new JPanel[2];
		
		buttonPanels[EAST_BUTTON_PANEL] = new JPanel(null); //TODO GridLayout?
		buttonPanels[EAST_BUTTON_PANEL].setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
		buttonPanels[EAST_BUTTON_PANEL].setBounds(0, 0, 110, 110);
		frame.add(buttonPanels[EAST_BUTTON_PANEL]);
		
		BildWechsel bildWechsel = new BildWechsel();
		for(byte b = 0, x = 0, y = 0; b < 9; b++, x++)
		{
			JButton button = new JButton(icons[x][y]);
			button.setBounds(30 * x + 10, 30 * y + 10, 30, 30);
			button.addActionListener(bildWechsel);
			buttonPanels[EAST_BUTTON_PANEL].add(button);
			
			if(x == 2)
			{
				x = -1;
				y++;
			}
		}
		
		buttonPanels[WEST_BUTTON_PANEL] = new JPanel(null); //TODO
		buttonPanels[WEST_BUTTON_PANEL].setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
		buttonPanels[WEST_BUTTON_PANEL].setBounds(110, 0, 110, 110);
		frame.add(buttonPanels[WEST_BUTTON_PANEL]);
		
		for(byte b = 0, x = 0, y = 0; b < 9; b++, x++)
		{
			JButton button = new JButton(icons[x][y]);
			button.setBounds(30 * x + 10, 30 * y + 10, 30, 30);
			button.addActionListener(bildWechsel);
			buttonPanels[WEST_BUTTON_PANEL].add(button);
			
			if(x == 2)
			{
				x = -1;
				y++;
			}
		}
		
		frame.setVisible(true);
	}

	public void actionPerformed(ActionEvent e)
	{
		if(pressedButton == null)
		{
			pressedButton = (JButton)e.getSource();
		}
		else
		{
			Icon[] buttonIcons = new Icon[2];
			buttonIcons[BUTTON_SOURCE] = pressedButton.getIcon();
			buttonIcons[BUTTON_DESTINATE] = ((JButton)e.getSource()).getIcon();
			
			pressedButton.setIcon(buttonIcons[BUTTON_DESTINATE]);
			((JButton)e.getSource()).setIcon(buttonIcons[BUTTON_SOURCE]);
			
			pressedButton = null;
		}
	}
}

splitImage() teilt das Originalbild in 9 Teile auf, setFrame() generiert die Buttons und der ActionListener kümmert sich um die Interaktion.
 

Anhänge

  • image.png
    image.png
    209 Bytes · Aufrufe: 58
Du hast das Bild im falschen Ordner. Bei Eclipse wäre das der Ordner des Projektes, also der in dem auch standartgemäß der Ordner scr und bin ist. Wies bei anderen Umgebungen ist weiß ich nicht, gibt warscheinlich aber eh keinen Unterschied.
 

Anhänge

  • Unbenannt.PNG
    Unbenannt.PNG
    1,1 KB · Aufrufe: 22
ich habe das Bild auch in dem src als auch in dem Package BildWechsel, aber trotzdem nur schwarzes Bild...
meine Umgebung ist auch Eclipse, normaleweise geht es so, wenn ich das Bild im Package habe.
 
Warscheinlich, weil du mit getClass().getResource(String) über die URL lädst, aber in dem Fall muss es in ...\Workspace\Projectordner\image.png liegen. Du kannst aber natürlich auch in Zeile 38 die Ladeart oder den Pfad ändern, solange in der Variable originalIcon am Ende das Bild steht.
 
es gehts... ich weisse nicht warum.

Das Spiel ist ähnlich wie ich vorstelle, aber es sollte nur von dem linken klickt und rechten klickt oder von dem rechten klickt und linken klickt, die Bilder vertauscht werden können. In dem BildWechsel.jar ist es erlaubt, 2 mal Klickt vom linken klickt oder 2 mal Klick von rechten klickt, um die Bilder zu vertauschen.

ich gucke mir den Code an, die Bilder müssen noch durcheinander/randomize gemacht. so dass die Aufgabe von dem Spiel besteht.
.., danach eine Finishmeldung muss noch geben, wenn die Bilder aufgeräumt werden.

Schon wäre mein Leben gerettet..
 
Dafür habe ich die beiden JPanels als Klassenvariable abgespeichert. Du kannst mit getComponents(), einer Schleife, und eventuell noch instanceof herausfinden, auf welchen JPanel der Source- oder Destinatebutton steht und das einfach vergleichen.

Um festzustellen, ob sie geordnet sind, könntest du z. B. die JButtons überschreiben, ihnen beim erzeugen ein byte als ID übergeben (z. B. die Schleifenvariable 'b'), und dann die Schleife durchgehen und jeweils prüfen, die Icons der JButton's die selben in den Klassen-Array sind. Damit sind die Icons der Buttons logischer weiße in der selben Reihenfolge, wie die nacheinander erstellten Einzelteile. Ginge aber auch per HashMap, wenn du ständig neue Werte mit der Position verknüpfst, und entfernst, beim überschreiben wäre der obere Tip natürlich hinfällig, weil du einfach die ID des Panel's in den 2 Schleifen im Construktor weitergeben kannst.

Zum mixen der Bilder würde ich zuerst je Panel eine Schattenkopie des Icon-Arrays erstellen lassen, ein Zufallsfeld des Arrays mit Math.random * x aussuchen, und in einer do so lange durchrennen, bis das Feld != null ist. Danach das Feld als Icon an den Button weitergeben und es in der Kopie auf null setzen.

Denke sollte alles so klappen, baust du jetzt mit ausführbaren Code-Beispiel sicher einfach ein, und am Ende überblickst du den Code sowieso komplett.
 
Zuletzt bearbeitet:
Wo ist das Problem?

Zeile 56:
frame.setSize(1020, 530);

Zeile 63:
buttonPanels[EAST_BUTTON_PANEL].setBounds(0, 0, 500, 500);

Zeile 70:
button.setBounds(160 * x + 10, 160 * y + 10, 160, 160);

Zeile 83:
buttonPanels[WEST_BUTTON_PANEL].setBounds(510, 0, 500, 500);

Zeile 89:
button.setBounds(160 * x + 10, 160 * y + 10, 160, 160);

Aber wie in den Kommentaren erwähnt, du solltest besser LayoutManager verwenden. FlowLayout ordnet Komponenten, wenn der Platz reicht horenziontal nacheinander an, das Grid(Bag)Layout in einen 2D-Raster.
Das sichert auch die Kompatiblität zu anderen OSes, habe mal gelesen, dass das null-Layout auf anderen OSen anderst ausschaut als am Root. Verstehe ich zwar nicht, da es ja Pixelgenau ist, aber würde kein Risiko eingehen.
 
Zuletzt bearbeitet:
ich verstehe nicht, wie JPanel mit .getComponent() funktioniert
weil buttonPanels.getComponent nicht geht.

ich habe mich so vorgestellt, ich mache if Schleife bei

<JAVA>
public void actionPerformed(ActionEvent e)
{
if(pressedButton == null)
{
pressedButton = (JButton)e.getSource();
}
else
{
Icon[] buttonIcons = new Icon[2];
buttonIcons[BUTTON_SOURCE] = pressedButton.getIcon();
buttonIcons[BUTTON_DESTINATE] = ((JButton)e.getSource()).getIcon();


if (pressedButton.getComponent(WEST_BUTTON_PANEL) == ((JButton).getComponent(WEST_BUTTON_PANEL))){
pressedButton = null;
system.out.println("nur klickt von panel1 und panel2");
}
pressedButton.setIcon(buttonIcons[BUTTON_DESTINATE]);
((JButton)e.getSource()).setIcon(buttonIcons[BUTTON_SOURCE]);

pressedButton = null;
}
}

</JAVA>

die code geht nicht, das liegt daran, dass pressedButton zwar JButton ist, aber (JButton) keine JButton ist...
 
Zurück