I have a weird issue... I'm a relatively new "enthusiast" Java programmer (I used to make my living hacking Perl, in a previous career), working on my first semi-real application. "Main-Class" is the MyApp class, which creates a UserInputDialog instance.
UserInputDialog is a class I wrote that extends JFrame, implements ActionListener and KeyListener, uses FlowLayout, and presents the user with a JLabel, JTextField, and Cancel/OK JButtons. When the JTextField generates a KeyEvent where keyReleased() == KeyEvent.VK_ENTER, or when the "OK" JButton generates an ActionEvent, UserInputDialog does some input validation, calls setVisible(false), and then calls MyApp.doSomething( JTextFieldInstance.getText() ).
That all works perfectly. But now I'm trying to add a progress window to MyApp, as doSomething() can occasionally take a fair amount of time to complete.
I created the ProgressWindow class, which extends JFrame, uses BorderLayout, and tosses a JProgressBar in .NORTH and a JScrollPane (wrapping a JTextArea) in .CENTER. ProgressWindow works perfectly when instantiated from ProgressWindowTester and fed test data. It also works fine if I copy-and-paste the test for loops from ProgressWindowTester into MyApp and don't have MyApp instantiate UserInputDialog (i.e., there's nothing inherent in MyApp that's causing this behavior; it seems to be some sort of interaction I'm not understanding, between UserInputDialog and ProgressWindow).
But when I try to use ProgressWindow in MyApp as intended, i.e., ProgressWindow setVisible(true), I get a blank Swing window (of the proper size, and with the title bar set properly). The JProgressBar and JScrollPane / JTextArea components don't appear. The ProgressWindow methods are being called by MyApp properly (System.err.println() messages show proper interaction), everything appears to be working fine, just, the components that should be visible in ProgressWindow ... aren't.
I can post code snippets, but it's kind of convoluted, and I'm probably just missing something obvious...
I'm familiar with the concept of separating UI and business logic generally (e.g., I used HTML::Template and Class::DBI and CGI::Application when building Perl applications), but I'm not sure I'm "doing it right" in Java...
Thanks in advance!
Oh, I get exactly the same behavior on the two environments I've tried the code in: javac 1.6.0_29 on Mac OS X 10.6.8 ("Snow Leopard"); and javac 1.7.0_02[1] on the Fedora 15 Linux distribution, kernel 2.6.31.10-3, LXDE desktop environment.
[1] Downloaded directly from oracle.com; I;m not using OpenJDK (I know JDK 7 is based on OpenJDK) or gcj or anything like that
You've got a concurrency in Swing issue where you're trying to do a long running process on the Swing event thread or EDT. Since this thread is responsible for drawing all components and for processing user input, if it is tied down by your long-running process, your GUI will be effectively frozen until the process is complete. The key is to use a background thread such as that provided by a SwingWorker for long-running processes, so the event thread doesn't get locked. Check out Concurrency in Swing for more information on this. Also check out the JProgressBar Tutorial for other insights on how to use progress bars with background threads.
Also, you'll not want to use a JFrame where a dialog, such as a JDialog, is much more appropriate. Also, you'll want to avoid use of KeyListeners with Swing. Much better would be to simply add an ActionListener to your JTextField since its default behavior is to respond to presses of the key.
Oh, and welcome to StackOverflow.com!
Related
Is there a possibility to prevent a JOptionPane dialog from blocking the interaction with the rest of the program, especially child JFrames? In my GUI, I launch a JFrame and want a message dialog to pop up after the child is closed to remind the user of something, but they launch parallel and the reminder blocks the child frame from being used.
Like here:
popupObjMan newPopup1 = new popupObjMan(gatewayAbstract, gatewayAbstractID);
JOptionPane.showInternalMessageDialog(this, "REMINDER: DO REFRESH");
I've tried to set the popup always on top, but this doesn't quite do the job.
I have no problem with them launching parallel (I'd even prefer it), but I could not work my head around it yet.
I just started Java programming ,so sorry in case that'd be something obvious.
A JOptionPane normally need to be modal. It shows something important and waits till the user answers with whatever option you give him (e.g. ok-button, yes/no-buttons, ...)
But there are several ways to reach your target.
(a)
Normally a JOptionPane creates a modal window.
You need a modeless window which does not block other windows.
https://docs.oracle.com/javase/tutorial/uiswing/misc/modality.html
(b)
You can start different threads to work for your different windows. They can have windows which are shown whenever the responsible thread commands them to. This is a bit difficult and can lead to memory-troubles.
(c)
You can write your own message-panels (e.g. notificaton) which are shown when and how long you like.
Bigger projects use different of these ways to achieve their goals.
A JOptionPane is a component, just like a JPanel. As a component it can be added to any other panel.
The JOptionPane API provides static methods to create a show the JOptionPane on a modal JDialog by default. You can't change this behaviour.
However, you can manually add the JOptionPane to a non-modal JDialog that you create. This is extra work as you now need to handle the closing of the dialog and processing the clicked button.
If you really want to do this then read the JOptionPane API. There is a section on Direct Use which demonstrates the basic code needed to add the JOptionPane to a JDialog.
Similar to this question I have the problem that the first JFrame I open takes way longer than ones afterward. I have an application that opens JFrames based on user input in the console. Because of this, I would have time to load the JFrame stuff in advance in a separate thread. What function of Swing or AWT should I call for this initialization to be executed (the other StackOverflow answer refers to some sun package which is no longer in the JRE/JDK)?
Swing: Just call everything you normally need to setup the GUI but don't invoke setVisible(true) on the JFrame until you want to display it. Note that the GUI should be created on the EDT, i.e. using SwingUtilities.invokeLater.
I want to make a Keylogger happen in Java Swing. I could manage to make a simple keylogger that catches Keystrokes and writes them to a logfile, when the focus is on the Swing Window. Since the focus has to be on the window, is it possible to make an invisible JFrame, that is always on top?
Something like this:
public class Logger extends JFrame implements KeyListener
logger.setVisible(false);
logger.setAlwaysOnTop(true);
Is this possible in Java?
So, you want a key logger that record keystroke even the focus is not on Java Swing window, right?
Java itself cannot do this, but Java Native Interface (JNI) can. You could Google "Java System Hook" and download the JAR from Github. (https://github.com/kristian/system-hook/releases) In one word, it keeps recording your keyboard as long as the program runs, regardless of which window you are focusing on.
The way I use it: I wrote a program that keep running while I play games and it can print out whatever key I press in the game.
I have a fairly simple Java Application I created with JFrames. There is more than one JFrame in my program. I have a menu launching at the beginning of the program. After going through the menu, I have the menu JFrame disposed.
The main JFrame has a menu button that should launch the exact same menu at a later time. However, when you launch the menu from inside of the ActionListener (when you press the menu button), the JFrame doesn't launch properly. None of the components show up and colors are off.
However, when the menu is launched from outside of the ActionListener, the JFrame shows up perfectly. I have tried multiple methods to fix this, but none of them have worked.
My full program code is available by clicking here.
The main class is "LetsMultiply5.java". This class also sets up the ActionListener.
The JFrame causing the problem is "MenuWindow.java".
"LetsMultiply5.java" calls the "Booter.java" class, which then calls the "MenuWindow.java".
"MainWindow.java" is the JFrame that has the "Menu" button.
For proof, "SpeedModer.java" calls the menu window after it has been disposed, and works.
================================EDIT================================
Also, I'd like to let you know that I realize my code is a little bit messy. I am not sure how else to write the code for this program.
I am forced to use Thread.sleep(x); because the Swing timers aren't what I am looking for. The Swing timers activate an ActionListener when the timer goes off. I need a system that will wait a second before continuing on with the code.
I realize that the while (repeater==0) loop with ActionListeners inside of it seems crazy, but that was the only way I could get it to work. If I put a single ActionListener and just had the while loop do no code inside of it, nothing happens when I press the button.
I would, as MadProgrammer mentioned:
Advice: Scrap your current approach and start again.
However, the way that I have my program currently coded is the only way that I know how to get what I need to do done. I read the tutorials, but still don't know how to improve the code in the way that you told me.
I thank everyone for trying to tell me to improve my bad "Java grammar", but as far as I am concerned, I am not going to continue this program for the next 20 years and make my millions off of it.
I have looked at the Swing timers before and I understand the whole new Timer(speed, this); concept, but I don't understand how this would make my code any better.
If anyone would like to show me how to fix my ActionListeners or Thread.sleep(x); lines, please tell me. Thank you.
You're blocking the Event Dispatching Thread with Thread.sleep(3000); - Don't do this, it will prevent the UI from been painted
See Concurrency in Swing for more details about the problem and How to use Swing Timers for a possible solution
You may also want to consider having a look at The Use of Multiple JFrames, Good/Bad Practice? and consider using CardLayout or JTabbedPane
If you need to block the user temporarily (to display a error message or gather important details), consider using a modal JDialog. See How to Make Dialogs for more details
I've spent the last few days putting together a game that runs as an Applet, but I would also like to have it available as an Application.
I've tried placing the applet in a frame, but I only get a black screen (and the occasional menu screen) when doing so. The applet still runs and the sound still plays, but there is nothing else.
I would like to not have to break down the code and rewrite it for a standalone application, as it's time consuming, but if there's no other way, then I'll do what I have to do. The program is a little complex in that the "main" class (containing all the media information, game related events, etc.) is an extension of an Applet class (containing the KeyListener, init() event, run() event, etc.) so maybe I am just trying to place the wrong thing in a frame?
Here is a link to the src folder for the game. I have tried putting both the AWPASG class and the Game class in a frame and seen the same results for both.
Any help would be greatly appreciated.
Source Code/Media
http://www.mediafire.com/?4eslqqr4aoh33j1
That's because your class design is not very good. You've bunched everything together in 2 classses, isntead of separating at least the UI Widgets (panels, etc, etc) from the UI Container.
Also you're using the old style AWT Applet and Panel. You should use the new Swing JApplet and JPanel (and all opthers JXxx components)
In short, try isolating your GUI building (painting) into a class that extends JPanel (or contains a JPanel). Then you can have 2 separate startup classes, one that puts your game JPanel inside a JApplet and one that puts it into a JFrame (and thus gives you the possibility to start it as a Desktop application).
Also you might want to separate your GAME init logic from the Applet init lifecycle, your game should be able to initialize without caring about the underlieing GUI technology.