I'm quite new to programming so I don't know the right way to do things and have been just experimenting a bit. I want to create a runnable where I can move back and forth between different content. The following works when run from inside eclipse, but if I export it as a JAR file, once I've moved forward once and then back again, moving forward won't give me the content anymore, but just the back button.
I tried something like this:
public class TestMain extends JFrame {
static PanelClass panel;
static boolean inUse = false;
public static void main(String[] args) {
panel = new PanelClass();
final TestMain test = new TestMain();
final Container container = test.getContentPane();
container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
test.setSize(500, 500);
final JButton back = new JButton("Back");
back.setAlignmentX(Component.CENTER_ALIGNMENT);
back.setMaximumSize(new Dimension(200, 80));
back.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
test.getContentPane().removeAll();
test.setContentPane(container);
test.getContentPane().revalidate();
}
});
final JButton exit = new JButton("Exit");
exit.setAlignmentX(Component.CENTER_ALIGNMENT);
exit.setMaximumSize(new Dimension(200, 80));
exit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
JButton problem = new JButton("Problem");
problem.setMaximumSize(new Dimension(200, 80));
problem.setAlignmentX(Component.CENTER_ALIGNMENT);
problem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
inUse = true;
test.setContentPane(panel);
test.getContentPane().add(back);
test.getContentPane().revalidate();
}
});
container.add(problem);
container.add(exit);
test.setVisible(true);
test.setDefaultCloseOperation(EXIT_ON_CLOSE);
test.setLocationRelativeTo(null);
while (true) {
while (!panel.stop && !inUse) {
}
inUse = false;
panel = new PanelClass();
test.setContentPane(panel);
test.getContentPane().add(back);
test.getContentPane().revalidate();
}
}
}
And the class for what I want to have as the second content:
public class PanelClass extends JPanel {
JTextArea text = new JTextArea("Some text here!" + '\n' + '\n');
JButton button1 = new JButton("Button 1");
JButton button2 = new JButton("Button 2");
boolean stop = false;
public PanelClass() {
text.setEditable(false);
text.setMaximumSize(new Dimension(300, 300));
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
Dimension d = new Dimension(200, 60);
button1.setAlignmentX(Component.CENTER_ALIGNMENT);
button1.setMaximumSize(d);
button2.setAlignmentX(Component.CENTER_ALIGNMENT);
button2.setMaximumSize(d);
this.add(text);
this.add(button1);
this.add(button2);
}
}
What is the actual working way to do this? What if I have a lot of windows I'd like to be able to move back and forth between? I know it's a lot of bad/possibly-hard-to-read code, but I hope someone could help me out.
This is the code that runs when you press "Problem":
test.setContentPane(panel);
test.getContentPane().add(back);
test.getContentPane().revalidate();
and this is the code that runs when you press "Back":
test.getContentPane().removeAll();
test.setContentPane(container);
test.getContentPane().revalidate();
What is the sequence of calls when you press "Problem" then "Back" then "Problem"? It's this. (The revalidate() calls won't mess anything up, so I won't show them)
// Problem
test.setContentPane(panel);
test.getContentPane().add(back);
// Back
test.getContentPane().removeAll();
test.setContentPane(container);
// Problem
test.setContentPane(panel);
test.getContentPane().add(back);
Notice that you set the panel as the content pane, and then remove all the components from it when "Back" is pressed. The next time you press "Problem", the panel has no components on it, because you removed them.
did you try exporting as a runnable jar and choose package required libraries into generated jar when you exported as JAR from eclipse?
Related
Good evening! Thank you if you are reading this question. Sorry for the mistakes with grammar in the post.
I am having a problem with the Executable Jar File in Intellij Idea. The project contains some pictures, and I call them by using the JPanel. I expected it would display my pictures, but it wouldn't. It only shows me the text. I don't see any error message, and I follow some posts that talk about it, even that I try to use Mark Directory as | Resources but it doesn't work.
I find out that the file structure in the project and the .jar file are different. It doesn't include my resource folder and only show the files inside it. But, the class file have the path from the resource folder. Maybe that is the problem.
Can anyone show me how to build the.jar file without changing the file structure from project, or the way to display the images back to the .jar file?
Thank all of you for reading this post
public class WX_Class extends JFrame{
private static final long serialVersionUID=1;
public static void main(String[]args) {
WX_Class WX = new WX_Class();
}
public WX_Class() {
JPanel WX_Main = new JPanel(new BorderLayout());
//Features
JButton btn00 = new JButton("< Close tab");
btn00.setBackground(Color.yellow);
btn00.setForeground(Color.black);
btn00.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) {
dispose();
}
});
JButton lb1 = new JButton("UbuntuVN Respin Tips", new ImageIcon("features_file//UbuntuVN_Respin.png"));
lb1.setMaximumSize(new Dimension(400,200));
lb1.setBackground(Color.WHITE);
JPanel WX_Box1 = new JPanel(new GridLayout(20,20));
BoxLayout box = new BoxLayout(WX_Box1, BoxLayout.PAGE_AXIS);
WX_Box1.setLayout(box);
WX_Box1.setBackground(Color.white);
WX_Box1.add(btn00);
WX_Box1.add(lb1, BorderLayout.NORTH);
WX_Box1.add(new JLabel("Hello, welcome to the UbuntuVN Respin Tips"), BorderLayout.WEST);
WX_Box1.add(new JLabel("Find somethings that you need here"), BorderLayout.WEST);
JLabel wx_text1=new JLabel("Tips");
wx_text1.setFont(new Font("Serif", Font.BOLD, 20));
WX_Box1.add(wx_text1, BorderLayout.WEST);
WX_Main.add(WX_Box1, BorderLayout.WEST);
JScrollPane WX_Scroll = new JScrollPane(WX_Box1);
WX_Scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
WX_Main.add(WX_Scroll);
JLabel WX_text2 = new JLabel("Title: UbuntuVN Respin - Design for Vietnamese users");
WX_Box1.add(WX_text2);
JButton WX_btn1 = new JButton("See the post");
WX_btn1.setBackground(Color.YELLOW);
WX_btn1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
WX_Post1 post1 = new WX_Post1();
post1.setVisible(true);
dispose();
}
});
WX_Box1.add(WX_btn1);
WX_Box1.add(new JLabel("Title: Install UbuntuVN Respin"));
JButton WX_btn2 = new JButton("See the post");
WX_btn2.setBackground(Color.yellow);
WX_btn2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
WX_Post2 post2 = new WX_Post2();
post2.setVisible(true);
dispose();
}
});
WX_Box1.add(WX_btn2);
WX_Box1.add(new JLabel("Title: Install, remove, troubleshoot software"));
JButton WX_btn3 = new JButton("See the post");
WX_btn3.setBackground(Color.yellow);
WX_btn3.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) {
WX_Post3 post3 = new WX_Post3();
post3.setVisible(true);
dispose();
}
});
WX_Box1.add(WX_btn3);
//set Frame
setTitle("UbuntuVN Respin Tips");
WX_Main.setBackground(Color.white);
this.setSize(800, 600);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
this.setContentPane(WX_Main);
}
}
I'm creating a program that features a grid of 12 JPanels. When the "add image" button is pressed, an image appears in the first JPanel in the grid and a counter is incremented by one. From then onwards, every time the "add image" is clicked again, an image would be added to the next JPanel. For some reason, the button only adds an image to the first JPanel and then stops working. Here's the code I've got so far.
public class ImageGrid extends JFrame {
static JPanel[] imageSpaces = new JPanel[12];
int imageCounter = 0;
ImageGrid() {
this.setTitle("Image Grid");
setSize(750, 750);
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel p3 = new JPanel();
p3.setLayout(new GridLayout(3, 4, 10, 5));
p3.setBackground(Color.WHITE);
p3.setOpaque(true);
p3.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
for (int j = 0; j < imageSpaces.length; j++) {
imageSpaces[j] = setImageSpace();
p3.add(imageSpaces[j]);
}
MyButtonPanel p1 = new MyButtonPanel();
add(p1, BorderLayout.SOUTH);
add(p3, BorderLayout.CENTER);
}
public JPanel setImageSpace() {
JPanel test;
test = new JPanel();
test.setOpaque(true);
test.setPreferredSize(new Dimension(100, 100));
return test;
}
class MyButtonPanel extends JPanel implements ActionListener {
final JButton addImage = new JButton("Add Image");
ImageIcon lorryPicture = new ImageIcon(ImageGrid.class.getResource("/resources/lorry.png"));
JLabel lorryImage = new JLabel(lorryPicture);
MyButtonPanel() {
add(addImage);
addImage.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == addImage) {
imageSpaces[imageCounter].add(lorryImage);
revalidate();
repaint();
imageCounter++;
}
}
}
public static void main(String[] args) {
ImageGrid test = new ImageGrid();
test.setVisible(true);
}
}
You should be revalidating and repainting the panel, (which is the containter being affected by the addition), not the frame
imageSpaces[imageCounter].add(lorryImage);
imageSpaces[imageCounter].revalidate();
imageSpaces[imageCounter].repaint();
Diclaimer: This may work as a simple fix, but also note that a component (in this case your JLabel lorryImage) can only have one parent container. The reason the above fix still works is because you don't revalidate and repaint the previous panel, the label was added to. So you may want to think about doing it correctly, and adding a new JLabel to each panel.
if (e.getSource() == addImage) {
JLabel lorryImage = new JLabel(lorryPicture);
imageSpaces[imageCounter].add(lorryImage);
imageSpaces[imageCounter].revalidate();
imageSpaces[imageCounter].repaint();
imageCounter++;
}
Disclaimer 2: You should add a check, to only add a label if the count is less than the array length, as to avoid the ArrayIndexOutOfBoundsException
Side Notes
Swing apps should be run from the Event Dispatch Thread (EDT). You can do this by wrapping the code in the main in a SwingUtilities.invokeLater(...). See more at Initial Threads
You could also just use a JLabel and call setIcon, instead of using a JPanel
Have a little problem with some code i have writing to try out something. I have made a frame with a single button in it. When i click on this button, a new frame opens, which it should. I close down the new frame, and then click on the button again, to try see if it still works. The problem starts here, corse insted of opening a single new frame, it opens two new frames. Third time i click it opens 4 frames and so on. I have tried quite a few things, but sadly cant seem to find the reason why it is opening more frames. Please help.
package budget;
import java.awt.event.*;
import javax.swing.*;
public class GUI extends JFrame {
String labelPrefix;
JButton button;
JButton button2;
JLabel label;
public static void main(String[] args) {
JFrame f = new GUI();
f.setExtendedState(f.MAXIMIZED_BOTH);
f.setVisible(true);
}
public GUI() {
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
p.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
button = new JButton("Click Me");
label = new JLabel(labelPrefix);
p.add(button);
this.setTitle("Try");
getContentPane().add(p);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
button.addActionListener(new MyActionListener());
}
class MyActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
button.addActionListener(this);
labelPrefix = "Try";
JFrame f2 = new GUI(label, labelPrefix);
f2.setExtendedState(f2.MAXIMIZED_BOTH);
f2.setVisible(true);
}
}
public GUI(JLabel label, String labelPrefix) {
JPanel p2 = new JPanel();
button2 = new JButton("Close");
p2.add(label);
p2.add(button2);
this.setTitle("Try");
getContentPane().add(p2);
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
pack();
button2.addActionListener(new MyActionListener2());
}
class MyActionListener2 implements ActionListener {
public void actionPerformed(ActionEvent e) {
button2.addActionListener(this);
dispose();
}
}
}
Clearly, the problem is here:
button.addActionListener(this);
Every time you click the button, it adds the listener yet another time to the button.
Simply remove that line and the error will go away. Once a listener is added to a button, it stays there. It isn't "consumed" after being triggered.
Check the first line in the actionPerformed of MyActionListener which states:
button.addActionListener(this);
This line should be removed.
I am making an applet and as part of my applet, I want this to happen: When the user presses "OK", the old components (some radio buttons) are removed, and a new JPanel is added, with a bunch of textfields.
However, I cannot figure out how to add a new component to the applet after it has started. I made the problem simpler by ignoring the removal part (Which I know how to do) and just adding a simple JLabel instead, but even that won't add!
Here is my code so far:
// imports omitted
public class Class extends Applet implements ActionListener
{
Button okButton;
CheckboxGroup radioGroup;
Checkbox radio1;
Checkbox radio2;
Checkbox radio3;
JLabel j;
public void init()
{
setLayout(new FlowLayout());
okButton = new Button("OK");
j = new JLabel("hello");
radioGroup = new CheckboxGroup();
radio1 = new Checkbox("Red", radioGroup,false);
radio2 = new Checkbox("Blue", radioGroup,true);
radio3 = new Checkbox("Green", radioGroup,false);
add(okButton);
add(radio1);
add(radio2);
add(radio3);
okButton.addActionListener(this);
}
public void repaint(Graphics g)
{
if (radio1.getState()) add(j);
}
public void actionPerformed(ActionEvent evt)
{
if (evt.getSource() == okButton) repaint();
}
}
What am I doing wrong?
You shouldn't override the repaint method, and certainly not add a component in this method. Just remove the radio buttons from the applet (using its remove method) and add the label in the applet in your actionPerformed method, the same way you add them in the init method.
You might have to call validate after.
Add components and then call validate() of your container. In this case yourApplet.validate(). This will trigger repainting and rearranging of all elements.
you could do something like
JFrame fr= new JFrame(); // global variables
JPanel panelToBeAdded = new JPanel();
JPanel initialPanel = new JPanel();
JTextField fieldToBeAdded = new JTextField();
panelToBeAdded.setPreferredSize( new Dimension(400,400));
initialPanel.setPreferredSize( new Dimension(400,400));
initialPanel.setVisible(true);
fr.add(initialPanel);
fr.setVisible(true);
fr.pack();
public void actionPerformed(ActionEvent ae) {
initialPanel.setVisible(false);
//radiobuttons.setVisible(false);---> hide the radio buttons
panelToBeAddedd.add(fieldToBeAddedd);
panelToBeAddedd.setVisible(true);
fr.add(panelToBeAddedd);
}
public void repaint( Graphics g ) {
// do something
}
What am I doing wrong?
Your repaint(Graphics) method is not the same method you are calling in your actionPerformed method.
Also, repaint is a pretty bad name for a method which is adding a new component.
public void swapComponents()
{
if (radio1.getState()) {
remove(radio1);
remove(radio2);
remove(radio3);
add(j);
validate();
}
}
public void actionPerformed(ActionEvent evt)
{
if (evt.getSource() == okButton) {
swapComponents();
}
}
When the user presses "OK", the old components (some radio buttons) are removed, and a new JPanel is added, with a bunch of textfields.
Use a CardLayout, as shown here. It is perfect for situations like this.
I'm having trouble with placing GUI components in an applet. I am looking for a way to place it using absolute coordinate and sizes.
Here's what I've done:
public class app extends JApplet {
public void init() {
setSize(450,450);
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
createGUI();
}
});
} catch (Exception e) {
System.err.println("Creation of swing components not finished");
}
}
public void createGUI() {
JMenuBar menubar = new JMenuBar();
JMenu menuFile = new JMenu("File");
JMenuItem openItem = new JMenuItem("Open");
menuFile.add(openItem);
menubar.add(menuFile);
setJMenuBar(menubar);
app_buttons ab = new app_buttons();
add(ab.button1);
add(ab.button2);
add(ab.button3);
}
}
public class app_buttons {
public JButton button1;
public JButton button2;
public JButton button3;
public apptextbox() {
button1 = new JButton("1");
button1.setBounds(20,20,20,20);
button2 = new JButton("2");
button2.setBounds(60,60,20,20);
button3 = new JButton("3");
button3.setBounds(90,90,20,20);
}
}
I can't figure out how to do it, either the components don't show or they fit the whole applet area. I want to specify for all my buttons, textareas, etc exactly how big they are and exactly where they will be placed. I've looked at tutorials on the web but it dosn't work, the components dont get displayed.
I don't want buttons, textareas, etc to resize either. Everything just static where I indicate them. For example when creating a JTextArea with (15,35) in size; it dosn't seem to matter because it resizes anyway.
Thanks
use
setLayout(null);
for your applet in your init().