I have a JFrame generated in my main method which contains a button that opens JDialogs every time it is pressed. The problem I'm having is that the JDialog is not visible in the taskbar, and the solutions I find on internet are when you generate a JDialog in your main.
How can I do to make every new window appear in my Windows taskbar?
For reference, my main looks like that:
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Main frame = new Main();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Main() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JButton btnNouvelleFentre = new JButton("Nouvelle fen\u00EAtre");
btnNouvelleFentre.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
Chat dlg = new Chat();
}
});
contentPane.add(btnNouvelleFentre, BorderLayout.SOUTH);
}
As you can see, I'm creating an instance of the class Chat, which extends JDialog. A new window is created, but none of them are in the taskbar.
AFAIK This is the default behaviour for dialogs on Windows and MacOS.
To display another item in the taskbar, you would need to create a new JFrame, this will mean, that if the you were relying on the modal state of the dialog, you will no longer have this functionality.
Having said all that, you should also have a read through The Use of Multiple JFrames, Good/Bad Practice? and consider using a JTabbedPane or CardLayout instead
Turns out if you pass a null parent to the JDialog constructor, your dialog will show in the taskbar.
JDialog dialog = new JDialog((Dialog)null);
// so if you say Chat extends JDialog, that would be:
Chat dlg = new Chat((Dialog)null);
(Dialog)null --> cast to java.awt.Dialog
This is an answer from the post:
Show JDialog on taskbar
It just took me 10 seconds fo find it ;)
Related
I set JTextField "rfid" to setEnabled(false) in MainGUI class and created method setRfidEnabled to be able to enable textfield from another class called CardLayout.
When I try to call it from CardLayout by button event listener it does nothing, I mean to textfield, because System.out.print("LOL"); works fine. MainGUI contains JFrame and by button calls another JFrame in CardLayout class.
When I initialize MainGUI class, it has Thread[Thread-2,6,main], but when I call CardLayout it becomes Thread[AWT-EventQueue-0,6,main], same as CardLayout itself. I tried to make "rfid" volatile, no success.
---Edited code---
MainGUI:
public class MainGUI {
JTextField rfid;
JButton button;
final JFrame frame;
final JPanel pane;
LayoutChanger layout = new LayoutChanger();
public MainGUI() {
rfid = new JTextField("", 10);
button = new JButton("CardLayoutSwitch");
frame = new JFrame("Main GUI Panel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout(5,5));
pane = new JPanel(new GridLayout(5, 5));
frame.add(pane,BorderLayout.CENTER);
pane.add(rfid);
pane.add(button);
rfid.setEnabled(false);
button.setEnabled(true);
frame.pack();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed (ActionEvent e){
layout.changeLayout(1);
}
});
}
public void setRfidEnabled() {
System.out.println("LOL");
rfid.setEnabled(true);
button.setEnabled(false);
}
}
LayoutChanger class:
public class LayoutChanger {
public static void main(String[] args) {
MainGUI gui = new MainGUI();
}
public void changeLayout(int i){
if (i == 1) {
CardLayout card = new CardLayout();
}
}
}
CardLayout class:
public class CardLayout {
JFrame frame;
JButton manual;
final JPanel pane;
MainGUI gui = new MainGUI();
public CardLayout() {
manual = new JButton("UID MANUAL");
frame = new JFrame("Card Scan Panel");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLayout(new BorderLayout(5, 5));
pane = new JPanel(new BorderLayout(5, 5));
manual.setPreferredSize(new Dimension(50, 25));
frame.add(pane, BorderLayout.CENTER);
pane.add(manual);
frame.pack();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
manual.addActionListener(new ActionListener() {
#Override
public void actionPerformed (ActionEvent e){
gui.setRfidEnabled();
}
});
}
}
As stated in the comments above by #matt
Every time you click on manual button, you're creating a new MainGUI().
You need to create a single instance, either in your constructor or in the ActionListener and ask if you already have an instance of it (i.e. a Singleton) and use it.
If you decide to use the first one, declare gui as a global variable:
MainGUI gui = new MainGUI();
And on your ActionListener have it changed as:
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(currentThread());
gui.setRfidEnabled();
//frame.dispose();
}
Then you have a single instance of it.
Also as stated by #Sergiy you don't really need all those threads
Here are some examples on how to use ActionListeners:
I'm trying to make a button to count characters in a text field
AppletViewer bugged and trying to involve a timer
Calculator returns 0.0 to all questions asked
Java - My action event doesn't work
Drawing shapes on a JForm java
Animated Sprites with Java Swing This one includes a Timer (Another thread that handles the animation but doesn't block the EDT)
As you can see in all the above examples, none of them required another Thread to handle the actions, the one that uses a thread is only for performing the animation and not to react to user clicks.
Recommended tutorial: How to use Actions
So I have a JOptionPane like this in the very beginning of my main method:
JFrame frame = new JFrame("Input");
String progName = JOptionPane.showInputDialog(frame, "Name?");
However, before I can start typing, I need to manually go click on the pop up. Is there any way to make it so that as soon as I run the program, it will automatically "select" the pop up so that when I start typing it will just be in the text box. If this can't be done with a JOptionPane, I am OK with other alternatives, I just need to get a user inputted string with the above constraint in mind.
I have created a simple example in which the logic for asking the user's name is concentrated in a single method. This method is called at the very start of the application and every time you click on a button.
This way, the user is forced to enter the data when the application starts and every time he/she wishes to change the entered value.
public class Jf53136132 extends JFrame {
private static final long serialVersionUID = -3336501835025139522L;
private JPanel contentPane;
public Jf53136132() {
setTitle("Jf53136132");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JPanel panel = new JPanel();
contentPane.add(panel, BorderLayout.CENTER);
JButton btnInvokeJoptionpane = new JButton("set some text on label");
panel.add(btnInvokeJoptionpane);
JLabel lblx = new JLabel("-x-");
panel.add(lblx);
getNewTextForLabel(lblx);
btnInvokeJoptionpane.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
getNewTextForLabel(lblx);
}
});
}
private void getNewTextForLabel(JLabel label) {
String inputText = JOptionPane.showInputDialog("Enter the text for the label");
System.out.println("you entered <" + inputText + ">");
if (inputText != null && !inputText.trim().isEmpty()) {
label.setText(inputText);
}
}
}
Notice how the method getNewTextForLabel(...) is called as soon as the label is added to the content pane and at every click of the button.
Also, as VGR correctly pointed out, it is a good practice to not run any Swing code inside the main application thread.
You can have a look at the java tutorials for swing (here's a classic example).
The following is some example code that runs the frame on a separate thread.
public class Main {
private static void createAndShowGUI() {
Jf53136132 f = new Jf53136132();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setPreferredSize(new Dimension(640, 480));
f.setLocationRelativeTo(null);
f.setVisible(true);
}
void execute() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public static void main(String[] args) {
new Main().execute();
}
}
I've written this:
JButton saveButton = new JButton(saveAction);
How do I then call it so that it displays within the window? (I've already got the code for the window, I just don't know how to call it so it shows)
saveButton.setVisible(true);
your_window.add(saveButton);
Thats all.
Firstly you should create some ContentPane for window (I guess you mean JFrame). Adding a button directly to window is not a good idea :P Next you can add your button to that pane:
panel.addComponent(button);
The last thing to do is:
frame.setContentPane(panel)
And that's all :P Just in a nutshell ;)
Use something like this
public class MainWindow extends JFrame {
public static void main(String[] args) {
MainWindow frame = new MainWindow();
frame.setVisible(true);
}
public MainWindow() throws IOException {
setTitle("Conveyor");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 851, 515);
contentPane = new JPanel();
JButton refreshButton = new JButton("refresh");
contentPane.add(refreshButton, BorderLayout.EAST);
}
}
My application offers the ability to launch a long-running task. When this occurs a modeless JDialog is spawned showing the progress of the task. I specifically make the dialog modeless to allow the user to interact with the rest of the GUI whilst the task runs.
The problem I'm facing is that if the dialog becomes hidden behind other windows on the desktop it becomes difficult to locate: There is no corresponding item on the task bar (on Windows 7), nor is there an icon visible under the Alt+Tab menu.
Is there an idiomatic way to solve this problem? I had considered adding a WindowListener to the application's JFrame and use this to bring the JDialog to the foreground. However, this is likely to become frustrating (as presumably it will mean the JFrame then loses focus).
You can create a non-modal dialog and give it a parent frame/dialog. When you bring up the parent frame/dialog, it also brings the non-modal dialog.
Something like this illustrates this:
public static void main(String[] args) throws IOException {
JFrame frame = new JFrame();
frame.setTitle("frame");
JDialog dialog = new JDialog(frame, false);
dialog.setTitle("dialog");
final JButton button = new JButton("Click me");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(button, "Hello");
}
});
final JButton button2 = new JButton("Click me too");
button2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(button2, "Hello dialog");
}
});
frame.add(button);
dialog.add(button2);
frame.pack();
dialog.pack();
frame.setVisible(true);
dialog.setVisible(true);
}
I'm trying to make a little game that will first show the player a simple login screen where they can enter their name (I will need it later to store their game state info), let them pick a difficulty level etc, and will only show the main game screen once the player has clicked the play button. I'd also like to allow the player to navigate to a (hopefully for them rather large) trophy collection, likewise in what will appear to them to be a new screen.
So far I have a main game window with a grid layout and a game in it that works (Yay for me!). Now I want to add the above functionality.
How do I go about doing this? I don't think I want to go the multiple JFrame route as I only want one icon visible in the taskbar at a time (or would setting their visibility to false effect the icon too?) Do I instead make and destroy layouts or panels or something like that?
What are my options? How can I control what content is being displayed? Especially given my newbie skills?
A simple modal dialog such as a JDialog should work well here. The main GUI which will likely be a JFrame can be invisible when the dialog is called, and then set to visible (assuming that the log-on was successful) once the dialog completes. If the dialog is modal, you'll know exactly when the user has closed the dialog as the code will continue right after the line where you call setVisible(true) on the dialog. Note that the GUI held by a JDialog can be every bit as complex and rich as that held by a JFrame.
Another option is to use one GUI/JFrame but swap views (JPanels) in the main GUI via a CardLayout. This could work quite well and is easy to implement. Check out the CardLayout tutorial for more.
Oh, and welcome to stackoverflow.com!
Here is an example of a Login Dialog as #HovercraftFullOfEels suggested.
Username: stackoverflow Password: stackoverflow
import java.awt.*;
import java.awt.event.*;
import java.util.Arrays;
import javax.swing.*;
public class TestFrame extends JFrame {
private PassWordDialog passDialog;
public TestFrame() {
passDialog = new PassWordDialog(this, true);
passDialog.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new TestFrame();
frame.getContentPane().setBackground(Color.BLACK);
frame.setTitle("Logged In");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
}
});
}
}
class PassWordDialog extends JDialog {
private final JLabel jlblUsername = new JLabel("Username");
private final JLabel jlblPassword = new JLabel("Password");
private final JTextField jtfUsername = new JTextField(15);
private final JPasswordField jpfPassword = new JPasswordField();
private final JButton jbtOk = new JButton("Login");
private final JButton jbtCancel = new JButton("Cancel");
private final JLabel jlblStatus = new JLabel(" ");
public PassWordDialog() {
this(null, true);
}
public PassWordDialog(final JFrame parent, boolean modal) {
super(parent, modal);
JPanel p3 = new JPanel(new GridLayout(2, 1));
p3.add(jlblUsername);
p3.add(jlblPassword);
JPanel p4 = new JPanel(new GridLayout(2, 1));
p4.add(jtfUsername);
p4.add(jpfPassword);
JPanel p1 = new JPanel();
p1.add(p3);
p1.add(p4);
JPanel p2 = new JPanel();
p2.add(jbtOk);
p2.add(jbtCancel);
JPanel p5 = new JPanel(new BorderLayout());
p5.add(p2, BorderLayout.CENTER);
p5.add(jlblStatus, BorderLayout.NORTH);
jlblStatus.setForeground(Color.RED);
jlblStatus.setHorizontalAlignment(SwingConstants.CENTER);
setLayout(new BorderLayout());
add(p1, BorderLayout.CENTER);
add(p5, BorderLayout.SOUTH);
pack();
setLocationRelativeTo(null);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
jbtOk.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (Arrays.equals("stackoverflow".toCharArray(), jpfPassword.getPassword())
&& "stackoverflow".equals(jtfUsername.getText())) {
parent.setVisible(true);
setVisible(false);
} else {
jlblStatus.setText("Invalid username or password");
}
}
});
jbtCancel.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setVisible(false);
parent.dispose();
System.exit(0);
}
});
}
}
I suggest you insert the following code:
JFrame f = new JFrame();
JTextField text = new JTextField(15); //the 15 sets the size of the text field
JPanel p = new JPanel();
JButton b = new JButton("Login");
f.add(p); //so you can add more stuff to the JFrame
f.setSize(250,150);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Insert that when you want to add the stuff in. Next we will add all the stuff to the JPanel:
p.add(text);
p.add(b);
Now we add the ActionListeners to make the JButtons to work:
b.addActionListener(this);
public void actionPerforemed(ActionEvent e)
{
//Get the text of the JTextField
String TEXT = text.getText();
}
Don't forget to import the following if you haven't already:
import java.awt.event*;
import java.awt.*; //Just in case we need it
import java.x.swing.*;
I hope everything i said makes sense, because sometimes i don't (especially when I'm talking coding/Java) All the importing (if you didn't know) goes at the top of your code.
Instead of adding the game directly to JFrame, you can add your content to JPanel (let's call it GamePanel) and add this panel to the frame. Do the same thing for login screen: add all content to JPanel (LoginPanel) and add it to frame. When your game will start, you should do the following:
Add LoginPanel to frame
Get user input and load it's details
Add GamePanel and destroy LoginPanel (since it will be quite fast to re-create new one, so you don't need to keep it memory).