I'm new to eclipse and java, I'm trying to switch between two panels with the use of a button. i want to test my project but when i try to run it it launches, gives no errors and then nothing happens.
Have i missed something that i need to do before to make this run?
This is the version i have and i downloaded it earlier today.
Eclipse IDE for Java Developers
Version: 2019-09 R (4.13.0)
Build id: 20190917-1200
And below is my code if there is anything stopping it from working in there.
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JLabel;
import java.awt.Font;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Music_Test {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Music_Test window = new Music_Test();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Music_Test() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JPanel Menu = new JPanel();
Menu.setBounds(6, 6, 438, 266);
frame.getContentPane().add(Menu);
Menu.setLayout(null);
Menu.setVisible(true);
JPanel Select_Level = new JPanel();
Select_Level.setBounds(6, 6, 438, 266);
frame.getContentPane().add(Select_Level);
Select_Level.setVisible(false);
JButton btnSelectLevel = new JButton("Select Level");
btnSelectLevel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Menu.setVisible(false);
Select_Level.setVisible(true);
}
});
btnSelectLevel.setBounds(158, 45, 117, 29);
Menu.add(btnSelectLevel);
JLabel lblMenu = new JLabel("Menu");
lblMenu.setFont(new Font("Comic Sans MS", Font.BOLD, 22));
lblMenu.setBounds(187, 17, 61, 29);
Menu.add(lblMenu);
JLabel lblSelectLevel = new JLabel("Select Level");
lblSelectLevel.setFont(new Font("Comic Sans MS", Font.BOLD, 22));
lblSelectLevel.setBounds(187, 17, 61, 29);
Select_Level.add(lblSelectLevel);
}
}
Start by using a different layout manager, FlowLayout or GridBagLayout might work better
JPanel centerPanel = new JPanel(new FlowLayout());
centerPanel.add(openReportSelection);
centerPanel.add(closeButton);
These layouts will honour the preferred sizes of your buttons
As for opening another window, well, you've already create one, so the process is pretty much the same. Having said that, you might consider having a look at The Use of Multiple JFrames: Good or Bad Practice? before you commit yourself to far.
A better approach might be to use a JMenuBar and JMenuItems to act as the "open" and "exit" actions. Take a look at How to Use Menus then you could use a CardLayout to switch between views instead, for example
From a pure design perspective (I know it's only practice, but perfect practice makes perfect), I wouldn't extend anything from JFrame and instead would rely on building your main GUIs around something like JPanel instead.
This affords you the flexibility to decide how to use these components, as you could add them to frames, applets or other components...
AND
Although you have implemented the actionPerformed method as per the ActionListener interface, you class is not of that that type as you haven't implemented the interface. Once you implement that interface and register it with the JButton btnAdd,
btnAdd.addActionListener(this);
the method will be called.
A more compact alternative might be to use an anonymous interface:
btnAdd.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// handle button ActionEvent & display dialog...
}
});
Side notes:
Using more than one JFrame in an application creates a lot of overhead
for managing updates that may need to exist between frames. The
preferred approach is to use a modal JDialog if another window is
required. This is discussed more Here
Related
I'm trying to get away from using NetBeans to create simple Swing GUIs and hence trying to get a better understanding of the whole container/layout mechanism. I'v been reading various things inline, especially https://docs.oracle.com/javase/tutorial/uiswing/components/toplevel.html.
In the example code below, I can see advantages to the second form, DialogJPanel(). For just one example, the JPanel can be given a border. My understanding is that the JPanel is actually getting added to the JDialog's content pane.
In the only "formal education" I had involving Java (3 years ago), we were taught to use the 3rd form, DialogBoth().
Is there an advantage to doing so? Perhaps in some cases where the content pane needs to be manipulated in some way? If so, what are those cases?
Or is the "both" form just to make clear to a reader of the code that the JPanel is really going onto the content pane of the JDialog?
And then there's the possibility of using setContentPane(jPanelOuter). Does that have some special purpose, in a practical sense?
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
public class DialogTest {
public static void main(String[] args) {
DialogContentPane dlgC = new DialogContentPane();
display(dlgC, "ContentPane");
DialogJPanel dlgP = new DialogJPanel();
display(dlgP, "JPanel");
DialogBoth dlgB = new DialogBoth();
display(dlgB, "Both");
}
public static class DialogContentPane extends JDialog {
public DialogContentPane() {
Container contentPane = this.getContentPane();
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
JRadioButton jRadioButton1 = new JRadioButton("My Radio Button, which does nothing");
jRadioButton1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
contentPane.add(jRadioButton1);
JCheckBox jCheckBox1 = new JCheckBox("My Check Box, which does nothing either");
jCheckBox1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
contentPane.add(jCheckBox1);
}
}
public static class DialogJPanel extends JDialog {
public DialogJPanel() {
JPanel jPanelOuter = new JPanel();
jPanelOuter.setLayout(new BoxLayout(jPanelOuter, BoxLayout.Y_AXIS));
JRadioButton jRadioButton1 = new JRadioButton("My Radio Button, which does nothing");
jRadioButton1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
jPanelOuter.add(jRadioButton1);
JCheckBox jCheckBox1 = new JCheckBox("My Check Box, which does nothing either");
jCheckBox1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
jPanelOuter.add(jCheckBox1);
this.add(jPanelOuter);
}
}
public static class DialogBoth extends JDialog {
public DialogBoth() {
Container contentPane = this.getContentPane();
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
JPanel jPanelOuter = new JPanel();
jPanelOuter.setLayout(new BoxLayout(jPanelOuter, BoxLayout.Y_AXIS));
JRadioButton jRadioButton1 = new JRadioButton("My Radio Button, which does nothing");
jRadioButton1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
jPanelOuter.add(jRadioButton1);
JCheckBox jCheckBox1 = new JCheckBox("My Check Box, which does nothing either");
jCheckBox1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
jPanelOuter.add(jCheckBox1);
contentPane.add(jPanelOuter);
}
}
public static void display(JDialog dlg, String title) {
Toolkit tk;
Dimension screenDims;
dlg.setTitle(title);
tk = Toolkit.getDefaultToolkit();
screenDims = tk.getScreenSize();
dlg.setLocation((screenDims.width - dlg.getWidth()) / 2, (screenDims.height - dlg.getHeight()) / 2);
dlg.pack();
dlg.setModalityType(JDialog.DEFAULT_MODALITY_TYPE);
dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dlg.setVisible(true);
}
}
There's no "immediate" advantage or disadvantaged other then the amount of code you need to type. Since Java 1.5 (I think) calls to things like add and setLayout on top level containers are automatically routed to the contentPane, this is why you may still see code which either uses getContentPane or setContentPane
To better understand what's happening, you need a better understanding of how a JFrame works...
A JFrame is composite component, made up of a series of layers. When Swing was first released, it was a requirement to use the contentPane directly in order to add components to it. This is eventually fixed (?) to allow you to add/remove components to the contentPane via the frame directly.
Just beware, removeAll, isn't routed to the contentPane and will remove the JRootPane, which is messy.
Some people prefer the "old" way, as it's obvious what's been done, some (like me, are lazy) and just prefer to get stuff done
I'm using WindowBuilder in Eclipse. I Created the following method to apply the same properties to certain types of buttons in my application.
In design view, my btn_Subscribe is invisible, but it appears when debugging.
However my btn_Login is visible in design view... I don't get it. I'm using my method when I add the JButton to the content
// ************************ LOGIN BUTTON ************************ \\
JButton btn_Login = new JButton("");
btn_Login.setIcon(new ImageIcon(DietProject.class.getResource("/images/img_login.png")));
btn_Login.setBounds(226, 89, 91, 32);
frmDietPlanner.getContentPane().add(setupCustomButton(btn_Login));
// ************************ SUBSCRIBE BUTTON ************************ \\
JButton btn_Subscribe = new JButton("");
btn_Subscribe.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
btn_Subscribe.setIcon(new ImageIcon(DietProject.class.getResource("/images/img_subscribe.png")));
btn_Subscribe.setBounds(10, 11, 103, 32);
frmDietPlanner.getContentPane().add(setupCustomButton(btn_Subscribe));
private JButton setupCustomButton(JButton jb)
{
// Remove the ugly border and background on the button
jb.setBorderPainted(false);
jb.setBorder(null);
jb.setContentAreaFilled(false);
jb.setCursor(new Cursor(Cursor.HAND_CURSOR));
return jb;
}
I assume frmDietPlanner is a JFrame which has by default BorderLayout manager.
By
frmDietPlanner.getContentPane().add(setupCustomButton(btn_Login));
frmDietPlanner.getContentPane().add(setupCustomButton(btn_Subscribe));
You are adding two buttons to the same location.
If you want to use setBounds set layout manager to null.
An MCVE for the problem and the solution looks like this:
import javax.swing.JButton;
import javax.swing.JFrame;
public class Frame extends JFrame {
Frame()
{
/////////////////////////////
setLayout(null);
////////////////////////////
setSize(400,400);
JButton btn_Login = new JButton("A");
btn_Login.setBounds(226, 89, 91, 32);
getContentPane().add(btn_Login);
JButton btn_Subscribe = new JButton("B");
btn_Subscribe.setBounds(10, 11, 103, 32);
getContentPane().add(btn_Subscribe);
setVisible(true);
}
public static void main(String[] args)
{
new Frame();
}
}
If I do the following, it shows up in the designer just fine. I don't get why using a method to apply the same properties would cause the designer not to display the button.... and at the same time it works perfectly fine for my login button! I really don't feel like doing this code for every single button I plan on using....
//frmDietPlanner.getContentPane().add(setupCustomButton(btn_Subscribe));
frmDietPlanner.getContentPane().add(btn_Subscribe);
btn_Subscribe.setBorderPainted(false);
btn_Subscribe.setBorder(null);
btn_Subscribe.setContentAreaFilled(false);
btn_Subscribe.setCursor(new Cursor(Cursor.HAND_CURSOR));
I am new to Java. I am trying to make text appear on a JLabel after a virtual button is clicked. However, I can't seem to find a solution to this. When I use the if statement it won't work. How can I make the text appear after the button was pressed?
import java.awt.event.*;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.JPanel;
import java.awt.Graphics;
public class autos extends JLabel implements ActionListener
{
private static final long serialVersionUID = 1L;
int now=0;
public autos(){
JLabel l=new JLabel("");
JFrame f=new JFrame("the title");
JPanel p=new JPanel();
JButton b=new JButton("click");
f.setBounds(400,500,400,500);
f.setVisible(true);
p.add(b);
f.add(p);
b.addActionListener(this);
p.setVisible(true);
p.add(l);
f.add(l);
if(now==1)
{
l.setText("hello");
l.setOpaque(true);
}
p.setBounds(200,200,200,200);
l.setBounds(100,100,100,100);
l.setOpaque(true);
f.setDefaultCloseOperation(f.EXIT_ON_CLOSE);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawRect(200,300,89,90);
g.drawString("buv",80,80);
repaint();
}
public static void main(String[] args)
{
new autos();
}
#Override
public void actionPerformed(ActionEvent e) {
now=1;
System.out.println("worked");
System.out.println(now);
}
}
You are setting up your label in your constructor code, which executes before the event handler which sets the now variable to 1.
What you can do is to move this code:
l.setText("hello");
l.setOpaque(true);
To here:
#Override
public void actionPerformed(ActionEvent e) {
now=1;
System.out.println("worked");
System.out.println(now);
l.setText("hello");
l.setOpaque(true);
}
This is a minimally working example of updating the text on button click. See the comments in code for the variety of changes.
import java.awt.event.*;
import javax.swing.*;
/* There is no need to extend label here. */
// public class autos extends JLabel implements ActionListener
public class autos implements ActionListener {
private static final long serialVersionUID = 1L;
int now = 0;
// this is now a class attribute, accessible to any method of this class.
JLabel l;
public autos() {
// this no longer declares a local variable, but instead
// creates an instance of the class attribute.
l = new JLabel("");
JFrame f = new JFrame("the title");
JPanel p = new JPanel();
JButton b = new JButton("click");
f.setBounds(400, 500, 400, 500); // this needs fixing!
f.setVisible(true);
p.add(b);
f.add(p);
b.addActionListener(this);
p.setVisible(true);
p.add(l);
f.add(l);
p.setBounds(200, 200, 200, 200); // this needs fixing!
l.setBounds(100, 100, 100, 100); // this needs fixing!
l.setOpaque(true);
f.setDefaultCloseOperation(f.EXIT_ON_CLOSE);
}
/* I cannot tell what this was trying to achieve, but whatever it was,
this was the wrong way to go about it. Never call repaint() from within
the paintComponent method as this creates an infinite loop! */
/*
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(200, 300, 89, 90);
g.drawString("buv", 80, 80);
repaint();
}
*/
public static void main(String[] args) {
// Swing GUIs should be created and updated on the EDT
new autos();
}
#Override
public void actionPerformed(ActionEvent e) {
/* This logic is questionable, but it denpends on what you are trying
to achieve here, something I'm not clear on. */
now = 1;
if (now == 1) {
l.setText("hello");
l.setOpaque(true);
}
System.out.println("worked");
System.out.println(now);
}
}
Edit
You added two comments at the setBounds part saying this needs fixing!. There I tried to resize the JPanel and JLabel but it's obvious it doesn't work.
How should I proceed here?
Here are some 'copy/paste comments' I regularly use:
Java GUIs have to work on different OS', screen size, screen resolution etc. using different PLAFs in different locales. As such, they are not conducive to pixel perfect layout. Instead use layout managers, or combinations of them along with layout padding and borders for white space.
See Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing? (Yes.)
Provide ASCII art or a simple drawing of the intended layout of the GUI at minimum size, and if resizable, with more width and height.
Now, to expand on those comments for this use-case:
That is advice I offer for people trying to make a null layout, but it also applies here.
This is relevant because there is one component (the custom painted one, if it exists) that needs to #Override the getPreferredSize(..) method to return a size as a suggestion to the layout managers or for packing the top level container.
The 3rd comment is because it is hard to advise how to code this GUI without knowing the end effect that is required.
Of course, I should point out: Each SO thread is expected to be a single, specific question. I really should have told you to start a new question on the other matters, but let it slide for this edit.
I am new to java and am getting to the advanced level of it, i have a problem in the GUI Controls, i made a button that when clicked opens up a new window like this:
JButton b = new JButton("Open New Window");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Window w = new Window();
w.setVisible(true);
}
});
this window contains other objects but i have been thinking of making the button in such a way that instead of opening a new JFrame, it opens everything in that same window without opening a new window, honestly i dont know how to do so please could i get some professional help
I think you want a card layout for this situation. Here is some code which should point you in the right direction.
class MyFrame extends JFrame {
public MyFrame() {
JComponent allMyStuff = new JComponent();
JComponent allMyOtherStuff = new JComponent();
this.getContentPane().setLayout(new CardLayout());
this.getContentPane().add(allMyStuff, "1");
this.getContentPane().add(allMyOtherStuff, "2");
CardLayout cl = (CardLayout) (this.getContentPane().getLayout());
cl.show(this.getContentPane(), "1");
JButton b = new JButton("Open New Window"); //add somewhere to first compoonent
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
CardLayout cl = (CardLayout) (this.getContentPane().getLayout());
cl.show(this.getContentPane(), "2");
}
});
}
}
I doubt the code runs but generally it holds the idea. You have stuff in one panel, and stuff in another panel, and you just want to switch between the two. The button of course needs to be added in the first panel (allMyStuff) somewhere.
I"m not clear on what it is exactly that you want to show in the GUI when the button is pressed, but perhaps you should consider creating different JPanel "views" and swap these views in the GUI using a CardLayout.
For example, check out these StackOverflow questions and answers:
Java CardLayout Main Menu Problem
Change size of JPanel using CardLayout
Java CardLayout JPanel moves up, when second JPanel added
Java swing; How to toggle panel's visibility?
Clear components of JFrame and add new componets on the same JFrame
gui multiple frames switch
JLabel displaying countdown, java
Within the action listener that you have introduced, you have the possibility to access to instance variables. Therefore you can add further elements to your GUI if you want. I've done a small demo, maybe this is kind of, what you want to do. In order to make your GUI better, you should consider of using layout managers.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class GUI {
JFrame frame;
JButton btn;
JButton compToAdd;
public GUI() {
frame = new JFrame("Testwindow");
frame.setSize(500, 500);
frame.setLayout(null);
btn = new JButton("test btn");
btn.setBounds(20, 20, 200, 200);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
compToAdd = new JButton("new Button");
compToAdd.setBounds(20, 220, 200, 200);
frame.add(compToAdd);
frame.repaint();
}
});
frame.add(btn);
frame.setVisible(true);
}
public static void main(String[] args) {
GUI gui = new GUI();
}
}
I'm using platform look-and-fell and on Linux my JTextArea is pretty readable
But on Windows it uses "Monospaced 9" and the text is very small.
Why and what is the best way to fix that?
Why default Windows look-and-fell uses such small font in JTextArea?
Instead of creating new font, it is better to derive existing font, because this way you'll save the font set by platform look and feel, and it may also avoid problems with unicode characters:
textArea.setFont(textArea.getFont().deriveFont(12f)); // will only change size to 12pt
Here's a solution that you can use to change all JTextAreas at once instead of using setFont() every time you add new text area:
UIManager.getDefaults().put("TextArea.font", UIManager.getFont("TextField.font"));
Call this on start of your application, after setting the Look and Feel.
Most L&Fs use the same font for JTextArea and JTextField, it's strange that Windows doesn't.
If you want a consistent look then use the Nimbus or Metal look and feel instead of the OS default. That will also allow you to tweak any settings. Plus I personally I think the Nimbus Look and Feel is much smoother looking than the others.
I've just used TextField font in TextArea...
textArea = new JTextArea();
textArea.setFont(UIManager.getFont("TextField.font"));
You can use the JTextArea1.setFont(Font(String name, int style, int size)) method to specify the specific type of font for a JTextArea component. As an example
jTextArea1.setFont(new Font("Arial Black", Font.BOLD, 8));
import java.awt.BorderLayout;
import java.awt.Font;
import javax.swing.JTextArea;
import javax.swing.WindowConstants;
import javax.swing.SwingUtilities;
public class NewJFrame extends javax.swing.JFrame {
private JTextArea jTextArea1;
private JTextArea jTextArea2;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
NewJFrame inst = new NewJFrame();
inst.setLocationRelativeTo(null);
inst.setVisible(true);
}
});
}
public NewJFrame() {
super();
initGUI();
}
private void initGUI() {
try {
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
{
jTextArea1 = new JTextArea();
getContentPane().add(jTextArea1, BorderLayout.NORTH);
jTextArea1.setText("This is a fox running slow");
jTextArea1.setFont(new Font("Arial Black", Font.BOLD, 8));
jTextArea1.setPreferredSize(new java.awt.Dimension(164, 114));
}
{
jTextArea2 = new JTextArea();
getContentPane().add(jTextArea2, BorderLayout.SOUTH);
jTextArea2.setText("This is a fox running slow");
jTextArea2.setFont(new Font("Book Antiqua", Font.ITALIC, 12));
jTextArea2.setPreferredSize(new java.awt.Dimension(384, 129));
}
pack();
setSize(400, 300);
} catch (Exception e) {
//add your error handling code here
e.printStackTrace();
}
}
}
Just do
textArea.setFont(new Font("Arial", Font.PLAIN, 16));
That changes all of the text inside of the textarea to the same size font.