I am making a Java gui project and it consists of two frames.
The problem is that when I call the secondframe from the firstframe, I have set it such that the firstframe visibility is set to false. The problem is how do I make the firstframe visible again by using a button from the second frame.
should i ditch this method and create a new jpanel instead??? Does jpanel have similar capabilities as jframe?
Consider using CardLayout. This way you can switch via multiple UIs without needing another frame. Here's how to use it.
Edit: As Guillaume posted in his comment, this answer from Andrew also covers how to use the layout.
Edit2:
As you requested a little more information about my latest post, here's how such a class may look like:
import javax.swing.JFrame;
public abstract class MyFrameManager {
static private JFrame startFrame,
anotherFrame,
justAnotherFrame;
static public synchronized JFrame getStartFrame()
{
if(startFrame == null)
{
//frame isnt initialized, lets do it
startFrame = new JFrame();
startFrame.setSize(42, 42);
//...
}
return startFrame;
}
static public synchronized JFrame getAnotherFrame()
{
if(anotherFrame == null)
{
//same as above, init it
}
return anotherFrame;
}
static public synchronized JFrame getJustAnotherFrame()
{
//same again
return justAnotherFrame;
}
public static void main(String[] args) {
//let's test!
JFrame start = MyFrameManager.getStartFrame();
start.setVisible(true);
//want another window
JFrame another = MyFrameManager.getAnotherFrame();
another.setVisible(true);
//oh, doenst want start anymore
start.setVisible(false);
}
}
This way you would only instantiate every JFrame once, but you could always access them via your manager class. What you do with them after that is your decision.
I also just made it thread-safe, which is crucial for singletons.
Related
Today, I am working on an Eclipse plugin project, where I am using the standard SWT_AWT bridge in order to plug my Swing components in:
public class MyView extends ViewPart {
public static final String ID = "HelloRCP.view";
Frame frame;
public void createPartControl(Composite parent) {
Composite composite = new Composite(parent, SWT.EMBEDDED | SWT.NO_BACKGROUND);
this.frame = SWT_AWT.new_Frame(composite);
SwingUtilities.invokeLater(new Runnable() {
private MainPanel swingPanel;
public void run() {
this.swingPanel = new MainPanel();
frame.add(swingPanel);
}
});
this.setResizeListener();
}
public void setFocus() {}
private void setResizeListener() {
this.frame.addComponentListener(new frameResizeListener(this));
}
public Frame getFrame() { return this.frame; }
}
I would like to get the "frameResizeListener" to somehow trigger an update of all subsequent Swing components (e.g. JPanels) constructed by the Swing Runnable instance, this upon the ViewPart's size-change, in order to achieve some kind of responsive design.
Somehow then, the underlying JPanels need to get to know about the ViewPart's Frame size...
I have read my fair share of SO Q&As, and only found the answer that "you need to pass a parameter at construction time". But my problem with this is that my usecase happes once the Components in question are already created and living...
The only solution that I see, so far, seems to break Thread-safety, by writing a shared file or property, and then signalling the Runnable to read it once done.
Can anyone else think of a better option please?
Thank you very much in advance for your support ! :) :)
Regards,
Peter
I'm currently trying to build a small program for school. If you click on a checkbox it should show other elements. I learned in python that you need a while loop because the program needs to go over the same lines again where you check if the box is checked but if i put a loop the whole program won't start. I don't understand why.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class test extends JFrame {
private JCheckBox moredetailscheck;
private JTextField inputfielduser;
public static void main(String[] args) {
test venster = new test();
venster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
venster.setSize(800, 600);
venster.setVisible(true);
venster.setTitle("true");
venster.setResizable(false);
}
public test() {
setLayout(new FlowLayout());
moredetailscheck = new JCheckBox("checkbox", false);
add(moredetailscheck);
inputfielduser = new JTextField(15);
while(true) { // you want to let the program keep going over these lines
if(moredetailscheck.isSelected()) {
add(inputfielduser);
}
}
}
If you click on a checkbox it should show other elements.
So, you would attach a listener to the JCheckBox, here an ItemListener, that responds when the state of the JCheckBox changes.
I learned in python that you need a while loop because the program needs to go over the same lines again where you check if the box is checked
This is called "polling" and is needed for linear console programs where you need to continually obtain input from the user, again in a "linear" fashion. In these types of programs, you the programmer are in complete control over program code flow, but that's not what you want here.
but if i put a loop the whole program won't start. I don't understand why.
That's because you're now using an event-driven GUI library, there the Swing library, and by calling a while (true) loop on the event thread, you completely block it, rendering your GUI useless. Your program is starting, but it can't construct the GUI, draw itself or listen for events.
Solution:
Get rid of the while (true) loop. Again, it is useful for simple console programs but not in this situation.
Add an ItemListener to your JCheckBox. You can find out how to do that in the check box tutorial
Don't keep adding items to your GUI. Use a CardLayout to swap views. The tutorial can be found here: CardLayout tutorial.
Or even better, have all the GUI items on the GUI at startup, but use the JCheckBox state to enable/disable an item.
As an aside, you will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.
For example:
import java.awt.event.ItemEvent;
import javax.swing.*;
public class TestCheckBox extends JPanel {
private static final long serialVersionUID = 1L;
private JCheckBox moreDetailsCheck = new JCheckBox("More Details", false);
private JTextField inputFieldUser = new JTextField(15);
public TestCheckBox() {
inputFieldUser.setEnabled(false);
add(moreDetailsCheck);
add(inputFieldUser);
// add a listener to the JCheckBox
moreDetailsCheck.addItemListener(e -> {
// if checkbox selected, enable the text field. else disable it
inputFieldUser.setEnabled(e.getStateChange() == ItemEvent.SELECTED);
});
}
private static void createAndShowGui() {
TestCheckBox mainPanel = new TestCheckBox();
JFrame frame = new JFrame("Test CheckBox");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
In Java, the AWT starts a thread to handle events automatically; you just let main finish and the program keeps running anyway until you call System.exit. You do need event handlers, though, for which any number of tutorials exist.
(Incidentally, your infinite loop comes before even showing your JFrame.)
I've seen similar questions answered but could not find an answer to my question. I have a Main Class, which has it's own JFrame. However, I've created a different Class where I've created another JFrame that prompts the user for some data. The Main Class is the main app. The secondary class is supposed to pop up before the main class GUI runs. I've created 2 different packages for each one of the Classes.
So, I'm trying to call an Object of the secondary Class from Main Class but the interface does not appear. I do not get any errors in the code and the App runs as if the Object of secondary Class is not being called at all. I am new to Java and would appreciate some lights on this.
My code is as follows:
Main Class
public class TempConverter extends javax.swing.JFrame {
public TempConverter() {
initComponents();
}
// More code
public static void main(String args[]) {
DemoUserData test = new DemoUserData();
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
test.setVisible(true);
new TempConverter().setVisible(true);
}
});
}
Secondary Class
public class DemoUserData extends javax.swing.JPanel {
public DemoUserData() {
initComponents();
}
}
Your JFrame is the main window. Before it is shown at the very early start a splash screen maybe shown, normally a small rectange with a logo.
It however seems, you want some input dialog, like say a login. That cannot be a JPanel, but must be a top-level window: JFrame or JDialog. Or one of the JOptionPane dialogs (asking string input, or whatevever).
Maybe you should make a JFrame for your current JPanel, run that.
.
DemoUserDataFrame test = new DemoUserDataFrame(this);
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
test.setVisible(true);
}
});
public class DemoUserDataFrame extends JFrame {
//private final JFrame tempConverter;
public DemoUserDataFrame(final JFrame tempConverter) {
//this.tempConverter = tempConverter;
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
tempConverter.setVisible(true);
}
});
}
...
}
In the above, closing test, will make the main JFrame visible.
In order to have a better overview, have the classes not refer one to another, you might look into the Model-View-Controller concept. Then there is one global "Controller" class as intermediator for all business logic. It holds the data (Model), and so on.
So the program I am making uses 2 threads: One for the GUI and one to do the work.
I want updates from the work thread/class to print out on JTextArea in GUI class.
Everything I tried didn't seem to work. I added lines to print out text on the console right after lines to add text to the JTextArea to make sure it had got to the line but everytime console got text but no changes happened to JTextArea in the GUI.
public static void consoleText(String consoleUpdate){
GUI.console.append(consoleUpdate);
}
I tried this in the work class but nothing happened.
Anyone know how to fix my problem?
Edit:
MAIN.JAVA
public class main {
public static void main(String[] args) {
Thread t1 = new Thread(new GUI());
t1.start();
}
GUI.JAVA
public class GUI extends JFrame implements Runnable{
public static JTextArea console;
private final static String newline = "\n";
public void run(){
GUI go = new GUI();
go.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
go.setSize(350, 340);
go.setVisible(true);
}
public GUI(){
setLayout(new FlowLayout());
console = new JTextArea(ConsoleContents, 15, 30);
add(console);
}
WORK.JAVA
...{
consoleText("\nI want this text on the JText Area");
}
public static void consoleText(String consoleUpdate){
GUI.console.append(consoleUpdate);
}
First, as has been said, your GUI should only run on the Event dispatch thread.
As it is written, your GUI class does two things : it's a frame, and a runnable, and both
are used completely independently. As a matter of fact, calling "run" on a your GUI object creates another, unrelated GUI object. That's probably the reason why you see nothing.
So I suggest making your main the following:
... main(...) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
GUI gui= new GUI();
gui.setVisible(true); // and other stuff
}
});
}
(I would also suggest getting rid of all "static" fields BTW. It's probably the source
of your problems, along with the weird place of the "run" method).
Now, your "consoleText" method, which I assume you call from another thread, should not
modify the text directly, but call SwingUtilities.invokeLater() to do so :
public void consoleText(final String consoleUpdate){
SwingUtilities.invokeLater(new Runnable() {
public void run() {
console.append(consoleUpdate);
}
});
}
(the "final" declaration is important, as it allows the Runnable to use the consoleUpdate variable).
I want to refresh(repaint) a jframe if an event in other class occurred, I use some thing like code below but somethimes this code didn't work:
static Container container;
public FrameConstractor()
{
...
container = getContentPane();
...
}
public static void refreshMethod()
{
container.repaint();
}
and I call refresh method when my event occurred; but this code repaint the frame for me some times and some times didn't do any thing!
I think your problem can be solved by changing refreshMethod to:
public static void refreshMethod()
{
container.invalidate();
container.validate();
}