Content of JFrame not showing - java

When the user hits "close" in one JFrame frame, I want the JFrame credits to be displayed showing my name and stuff for 2.5 seconds before the program exits. Now, credits is showing, but empty without the textArea and the Button - couldnt find whats wrong.
Heres my code:
For the closing operation of frame
frame.addWindowListener(new java.awt.event.WindowAdapter() {
#Override
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
int result = JOptionPane.showConfirmDialog(null, "Sind Sie sicher?", "Schließen", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (result == JOptionPane.YES_OPTION){
credits.setVisible(true);
try {
Thread.sleep(2500);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
System.exit(0);
} else {
//do nothing
}
}
});
For credits (just the class initializing the frame):
public class CreditsFrame extends JFrame {
Positioner pos = new Positioner();
private JPanel contentPane;
ImageIcon frameIcon = new ImageIcon("files/images/frameicon.png");
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
CreditsFrame frame = new CreditsFrame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public CreditsFrame() {
setIconImage(frameIcon.getImage());
setAlwaysOnTop(true);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(pos.posX(pos.screenX, 441), pos.posY(pos.screenY, 210), 441, 210);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
JTextArea txtarea = new JTextArea();
txtarea.setBounds(10, 11, 415, 125);
txtarea.setEditable(false);
txtarea.setBackground(Color.WHITE);
txtarea.setWrapStyleWord(true);
txtarea.setLineWrap(true);
txtarea.append("created by & more here");
contentPane.setLayout(null);
contentPane.add(txtarea);
JButton btnOk = new JButton("Ok");
btnOk.setBounds(154, 147, 89, 23);
btnOk.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
dispose();
}
});
contentPane.add(btnOk);
}
}
Any suggestions for a quick fix? Thanks.

Any suggestions for a quick fix?
Yes, don't call Thread.sleep(...) on the Swing event thread unless you want to put your entire GUI to sleep. Instead use a Swing Timer to handle the delay. Basically, the timer's ActionListener will be called after the milliseconds delay has passed.
e.g.,
frame.addWindowListener(new java.awt.event.WindowAdapter() {
#Override
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
int result = JOptionPane.showConfirmDialog(null, "Sind Sie sicher?", "Schließen", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (result == JOptionPane.YES_OPTION){
credits.setVisible(true);
new Timer(2500, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.exit();
}
}).start();
} else {
//do nothing
}
}
});
Also, look at The Use of Multiple JFrames, Good/Bad Practice?
Other issues that will bite you in the future:
You look to be using null layouts and setBounds. While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms different from the original one.
Never set a JTextAreas bounds as this will make it completely fail if it is placed within a JScrollPane and more text than can be displayed is added -- the scroll bars will seem not to work since you've artificially constrained the size of the text component.

Related

Can't Automatically Select JOption Pane showInputDialog

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();
}
}

Two buttons changing panel color to red or blue

my first post here. I'm currently in school and usually spend my time here on Stackoverflow looking for answers to homework, this time i'd thought that perhaps i'll put my code here and maybe i'll get help more precis and quicker! Anyways, my problem is that i've written a code which you can see below, and I'm new to swing, studied it for a few hours only. My problem is that I'm not quite sure how to proceed with my problem, I have 2 buttons, what i want is when you click on first button the panel will change to Red, second button the panel changes to blue, so far only Red works and I don't know how to implement it so that blue works aswell.
Would greatly appreciate your help! (Don't be shy about pointing out a few errors or help along the way that doesn't have with the buttons to do, as I said, I'm new :P)
public class FirstProgram extends JFrame {
public FirstProgram() {
initUI();
}
private void initUI() {
JPanel panel = new JPanel();
panel.setBackground(Color.yellow);
getContentPane().add(panel);
panel.setLayout(null);
JButton Colorbutton = new JButton("Red");
Colorbutton.setBounds(50, 60, 80, 30);
Colorbutton.setToolTipText("Panel changes to red");
Colorbutton.setBackground(Color.green);
JButton Colorrbutton = new JButton("Blue");
Colorrbutton.setBounds(1, 30, 90, 30);
Colorrbutton.setToolTipText("Panel changes to blue");
Colorrbutton.setBackground(Color.orange);
Colorbutton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
panel.setBackground(Color.red);
}
});
panel.add(Colorbutton);
panel.add(Colorrbutton);
setTitle("Time to change colors");
setSize(300, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
FirstProgram ex = new FirstProgram();
ex.setVisible(true);
}
});
}
}
you need another ActionListener. right now you just have one and it has just one behavior. create another one and tie to the 'Blue" button
JButton RedColorbutton = new JButton("Red");
RedColorbutton .setBounds(50, 60, 80, 30);
RedColorbutton.setToolTipText("Panel changes to red");
RedColorbutton.setBackground(Color.green);
JButton BlueColorbutton = new JButton("Blue");
BlueColorrbutton.setBounds(1,30,90,30);
BlueColorrbutton.setToolTipText("Panel changes to blue");
BlueColorrbutton.setBackground(Color.orange);
RedColorbutton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
panel.setBackground(Color.red);
}
});
BlueColorbutton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
panel.setBackground(Color.blue);
}
});
You've set an action listener for your Colorbutton, but not for Colorrbutton
Add this next to your other ActionListener
Colorrbutton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
panel.setBackground(Color.blue);
}
});
You are missing an ActionListener for the blue JButtton.
Similar to how you added the ActionListener to your ColorButton, your ColorrButton needs to have one registered. By the way, you may wish to change the ColorButton to redButton and the ColorrButton to blueButton or something like that to make things stick out better.
example:
Colorrbutton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
panel.setBackground(Color.blue);
}
});
For the sake of reducing duplicate code, you can simplify the logic even further by having your class implement ActionListener.
public class FirstProgram extends JFrame implements ActionListener {
Then, when you are instantiating your buttons, add a listener like so:
redButton.addActionListener(this);
blueButton.addActionListener(this);
And then in your implementation of actionPerformed you could do something like:
public void actionPerformed(ActionEvent e) {
switch (e.getSource()) {
case redButton:
panel.setBackground(Color.red);
break;
case blueButton:
panel.setBackground(Color.blue);
break;
}
}
Anytime the red or blue buttons performs an action, the actionPerformed will be triggered, and then the logic to determine which button was the source will take over from there. This will add a little bit of length to your code, but as(if?) your program grows, it will reduce complexity greatly

Translucent loading overlay for JFrame

I have a JFrame containing various components and I would like to add a translucent grey overlay over the top while the application is initializing various things. Ideally it would prevent interaction with the underlying components and would be able to display some "Loading..." text or a spinning wheel or something similar.
Is there a simple way to do this using Java and Swing?
Take a look at JRootPane and JLayeredPane http://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html#layeredpane
What you're asking about specifically sounds like a Glass Pane.
http://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html#glasspane
The Glass Pane prevents interaction with underlying components and can be used to display something on top of your JFrame.
As #David said, you can use the glass pane for displaying some loading text or image above the rest of the application.
As for the grey overlay: why don't you use the built in ability to disable components as long as your application is loading? Disabled components will get grayed out automatically and cannot be interacted with by the user.
Something like this:
public class LoadingFrame extends JFrame{
JButton button;
public LoadingFrame() {
button = new JButton("ENTER");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Application entered");
}
});
setLayout(new BorderLayout());
add(button, BorderLayout.CENTER);
}
public void startLoading(){
final Component glassPane = getGlassPane();
final JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
final JLabel label = new JLabel();
panel.add(label, BorderLayout.SOUTH);
setGlassPane(panel);
panel.setVisible(true);
panel.setOpaque(false);
button.setEnabled(false);
Thread thread = new Thread(){
#Override
public void run() {
for (int i = 5; i > 0; i--) {
label.setText("Loading ... " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// loading finished
setGlassPane(glassPane);
button.setEnabled(true);
}
};
thread.start();
}
public static void main(String[] args) {
LoadingFrame frame = new LoadingFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.startLoading();
frame.setVisible(true);
}
}

Java ComponentResized - Detect whether user resized the window or it was resized programatically

I have a JFrame in which I remove and add components and each time I do this, I resize the frame accordingly. I added a Component Listener but of course it gets triggered both by the user resizing the window and also by my setSize() methods.
Is there any way to see from the ComponentEvent whether the user resized the window or I did through setSize()?
The posible solutions I found are:
1. Use a flag - boolean resizing - which I set to true before setSize() and to false after that.
2. Add a mouseDragged listener and compare sizes before and after the drag.
The second one is definitely not a good choice. The first one would work but I would like to know if I can find in a simple way whether the user is the one who resized the window or not.
I resize the frame accordingly
Whats wrong with using pack()?
I remove and add components and each time I do this,
Then this is where you should set your Boolean value:
programResize == true:
panel.add(...);
frame.setSize(...); // this should cause the ComponentListener to fire
// the ComponentListener would then use programResize == false;
Or a better option option could be:
component.removeComponentListener(...);
panel.add(...);
frame.setSize(...);
component.addComponentListener(...);
I like this approach better because all the logic based on the manual update is self contained in one place and there is no need to define a Boolean variable.
Is there any way to see from the ComponentEvent whether the user
resized the window or I did through setSize()?
yes it is, use boolean flag reseted by Swing Timer
in the case that user resized window then ComponentListener firing a new event per every pixel, bunch of events
by determine the contianer set(Xxx)Size is this event fired only once time
example about events from ComponentListner
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
public class ComponentEventDemo extends JPanel
implements ComponentListener, HierarchyListener,
ItemListener {
private JFrame frame;
private static final long serialVersionUID = 1L;
private JTextArea display;
private JLabel label;
private JButton button = new JButton("Change Size");
private String newline = "\n";
public ComponentEventDemo() {
display = new JTextArea();
display.setEditable(false);
JScrollPane scrollPane = new JScrollPane(display);
scrollPane.setPreferredSize(new Dimension(350, 200));
label = new JLabel("This is a label", JLabel.CENTER);
label.addComponentListener(this);
JCheckBox checkbox = new JCheckBox("Label visible", true);
checkbox.addItemListener(this);
checkbox.addComponentListener(this);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Dimension dim = frame.getPreferredSize();
if (!dim.equals(new Dimension(800, 600))) {
frame.setPreferredSize(new Dimension(800, 600));
frame.pack();
} else {
frame.setPreferredSize(new Dimension(400, 300));
frame.pack();
}
}
});
JPanel panel = new JPanel(new GridLayout(1, 3));
panel.add(label);
panel.add(checkbox);
panel.add(button);
panel.addComponentListener(this);
frame = new JFrame("ComponentEventDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(scrollPane, BorderLayout.CENTER);
frame.add(panel, BorderLayout.PAGE_END);
frame.pack();
frame.setVisible(true);
}
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
label.setVisible(true);
label.revalidate();
label.repaint();
} else {
label.setVisible(false);
}
}
protected void displayMessage(String message) {
//If the text area is not yet realized, and
//we tell it to draw text, it could cause
//a text/AWT tree deadlock. Our solution is
//to ensure that the text area is realized
//before attempting to draw text.
// if (display.isShowing()) {
display.append(message + newline);
display.setCaretPosition(display.getDocument().getLength());
//}
}
#Override
public void componentHidden(ComponentEvent e) {
//displayMessage(e.getComponent().getClass().getName() + " --- Hidden");
}
#Override
public void componentMoved(ComponentEvent e) {
//displayMessage(e.getComponent().getClass().getName() + " --- Moved");
}
#Override
public void componentResized(ComponentEvent e) {
displayMessage(e.getComponent().getClass().getName() + " --- Resized ");
}
#Override
public void componentShown(ComponentEvent e) {
//displayMessage(e.getComponent().getClass().getName() + " --- Shown");
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ComponentEventDemo componentEventDemo = new ComponentEventDemo();
}
});
}
#Override
public void hierarchyChanged(HierarchyEvent e) {
displayMessage(e.getComponent().getClass().getName() + " --- Hierarchy changed");
}
}

Java - how do I gain focus on JTextArea when selecting a new JTabbedPane

I have a swing GUI with multiple JTabbedPanes; each tab contains two JButtons at the top, then a JTextArea (for user input), and a JTextField at the bottom for a result.
My problem is that I can't get the JTextArea to gain focus after switching tabs without either clicking in it with the mouse or using the tab key on the keyboard?
I have...
frame.addWindowFocusListener(new WindowAdapter() {
public void windowGainedFocus(WindowEvent e) {
textArea_1.requestFocusInWindow();
...and this works well when the app is first run (the textArea in the first tab has focus) but when I switch to another tabbedpane the first button now has the focus instead of the textArea, and when I switch back to the first tab the textArea has lost focus and once again the first button has focus.
I've tried adding a requestFocus to each textArea, and I've tried "Bring to front" on each textArea, and I've messed around with Focus Traversal but nothing I do seems to make the textArea gain focus on a tab change?
This has had me stumped for a week so any help will be gratefully received?
Add a ChangeListener to your JTabbedPane. Here's the general idea:
[Sorry, I used JTextFields instead of JTextAreas since I had an old stub laying around - but the idea is the same.]
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class JTabbedPaneDemo3 implements Runnable
{
JTextField txtFoo;
JTextField txtBar;
JTabbedPane tabbedPane;
public static void main(String[] args)
{
SwingUtilities.invokeLater(new JTabbedPaneDemo3());
}
public void run()
{
txtFoo = new JTextField(10);
final JPanel pnlFoo = new JPanel();
pnlFoo.add(new JButton("Button 1"));
pnlFoo.add(new JLabel("Foo"));
pnlFoo.add(txtFoo);
txtBar = new JTextField(10);
final JPanel pnlBar = new JPanel();
pnlBar.add(new JButton("Button 3"));
pnlBar.add(new JLabel("Bar"));
pnlBar.add(txtBar);
tabbedPane = new JTabbedPane();
tabbedPane.addTab("Tab 1", pnlFoo);
tabbedPane.addTab("Tab 2", pnlBar);
tabbedPane.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
Component comp = tabbedPane.getSelectedComponent();
if (comp.equals(pnlFoo))
{
txtFoo.requestFocusInWindow();
}
else if (comp.equals(pnlBar))
{
txtBar.requestFocusInWindow();
}
}
});
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(460, 200);
frame.getContentPane().add(tabbedPane, BorderLayout.CENTER);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
txtFoo.requestFocusInWindow();
}
}
I couldn't make "getSelectedComponent()" work for me, it just wasn't seeing any changes made to the tab selection, but I modified your suggestion slightly and took MadProgrammer's advice and added invokeLater...
tabbedPane.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
JTabbedPane pane = (JTabbedPane) e.getSource();
int selectedIndex = pane.getSelectedIndex();
if (selectedIndex == 0)
{
SwingUtilities.invokeLater( new Runnable() {
public void run() {
textArea1.requestFocusInWindow(); }});
}
else if (selectedIndex == 1)
{
SwingUtilities.invokeLater( new Runnable() {
public void run() {
textArea2.requestFocusInWindow(); }});
}
else if (selectedIndex == 2)
{
SwingUtilities.invokeLater( new Runnable() {
public void run() {
textArea3.requestFocusInWindow(); }});
}
else if (selectedIndex == 3)
{
SwingUtilities.invokeLater( new Runnable() {
public void run() {
textArea4.requestFocusInWindow(); }});
}
else if (selectedIndex == 4)
{
SwingUtilities.invokeLater( new Runnable() {
public void run() {
textArea5.requestFocusInWindow(); }});
}
}
});
...and now all is right with the world again! Thanks to all.

Categories

Resources