When I am running this, JLabel is not visible, but when I resize window (with mouse) JLabel is showed. Why?
import javax.swing.*;
import java.awt.*;
public class FrmTaoLogin extends JFrame {
private JPanel pnlLeft = new JPanel();
public FrmTaoLogin() {
super();
pnlLeft.setBorder(BorderFactory.createEtchedBorder());
pnlLeft.add(new JLabel("test1"));
getContentPane().add(pnlLeft,BorderLayout.SOUTH);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(200, 200);
}
public static void main(String[] args) {
FrmTaoLogin FrmLogin = new FrmTaoLogin();
FrmLogin.setVisible(true);
}
}
IIRC, this happens when you don't call Frame.pack(). It should work if you call 'pack()' as the last line of the constructor.
I suspect that the problem here may have to do with trying to build and show your GUI components outside of the Swing thread.
What if you change main() to invoke your GUI code on the Swing thread, like this?
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
FrmTaoLogin FrmLogin = new FrmTaoLogin();
FrmLogin.setVisible(true);
}
});
}
This look like some of the L&F bugs in older Java VMs on newer OS. For example on Windows 7 the most problems are solved first with 1.6.0_17. You should start your program with a console. If you see some stacktraces in the event thread then it is a problem of an L&F bug.
Thanx to all, problem resolved. I change Windows theme and all working fine. I think that's Windows Aero and my NVIDIA GeForce FX5500 problem. This card official not working with windows Aero.
Related
I am using Java 11 on Debian 4. I am trying to build a very basic Java GUI. To start with I have the following code:
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
public class BasicSwing extends JFrame {
JPanel p = new JPanel();
JButton b = new JButton("Hello");
public static void main (String[] args) {
new BasicSwing();
}
public BasicSwing() {
super("Basic Swing");
setSize(400,300);
setResizable(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
p.add(b);
add(p);
setVisible(true);
}
}
I have the X11 server running. The code does not fail but the GUI does not show up. I am not using Netbeans and I compile and run the code just as I would run and compile any other java code, ie with javac and java commands.The code does not stop and does not throw any error. Am I missing something very basic? I have seen a lot of discussion on the GUI not showing up but I am unable to find a solution to this problem given my specific development environment.
Instead of calling the setVisible method inside of your JFrame extended class's constructor, You should make a call on it in your main function.
Do it this way:
public static void main (String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
BasicSwing mySwingApp = new BasicSwing();
mySwingApp.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
Please read more about why I use a java.awt.EventQueue here.
Update:
It's not good practice to directly create a class that extends JFrame. Also, please read this too, for more clarification.
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 had some previous experience to swing applications at school, so I know how they work and will be fine designing them, but I am unsure of the best way to set my application up.
We only created smaller programs at school so we had almost all of our code in the constructor, but I want to create something larger, and am unsure of how I should set things up.
I have my base class with the constructor that will create my JFrame that I will use throughout the application, but what classes do I make to add my components, or use action listeners? I am unsure exactly of the proper way to do this, so a guiding step would be great.
Here is my class declaration/constructor:
public class SwingApp1 extends JFrame{
public SwingApp1() {
setTitle("Greens Tracker");
setSize(800,500);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
}
Now what do I put in my main, and in what manor should I be adding components?
Any help is appreciated, thanks!
Good way of setting up your JFrame is
public GUI() {
buildGUI();
}
private void buildGUI() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setSize(500, 300);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new GUI().setVisible(true);
}
});
}
I hope it helped :)
The program starts at the main as:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new SwingApp1().setVisible(true);
}
});
}
which can be abbreviated since Java 8 as:
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new SwingApp1().setVisible(true));
}
The JFrame constructor could be as follows. A setVisible I leave to the call,
and pack() will layout the contents.
public SwingApp1() {
setTitle("Greens Tracker");
setSize(800,500);
... add components, maybe in a separate method.
pack();
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
Actually look into MVC, Model View Controller.
I generally maky an XyzApplication class as controller, the JFrame being the main view and the separately kept data (in the application) the model.
It should be mentioned, that JavaFX may be slightly more advisable, say without FXML layout files. A bit more learning involved, but nicer behavior.
Other advise would be to use a build infrastructure like maven. That helps with libraries ("dependencies") and provides "best practices" like build directories (src/main/java, src/test/java, src/main/resources ...).
Of course a version control system like git or mercurial.
On the Linux platform, Frame::getBounds and Frame::setBounds do not work consistently. This has already been reported in 2003(!), see here:
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4806603
For convenience, I have simplified the stated code that results in a bug and paste it as:
import java.awt.Button;
import java.awt.Frame;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/** Demonstrates a bug in the java.awt.Frame.getBounds() method.
* #author Mirko Raner, PTSC
* #version 1.0 (2003-01-22) **/
public class GetBoundsBug extends Frame implements ActionListener {
public static void main(String[] arg) {
GetBoundsBug frame = new GetBoundsBug();
Button button = new Button("Click here!");
button.addActionListener(frame);
frame.add(button);
frame.setSize(300, 300);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent event) {
Rectangle bounds = getBounds();
bounds.y--;
setBounds(bounds);
bounds.y++;
setBounds(bounds);
}
}
Unexpected behavior: Upon clicking the button the window is shifted slightly below! (On my system by 28 pixels each click.)
Here is a screen recording: https://youtu.be/4qOf99LJOf8
This behavior has been around for 13+ years, so probably there won't be any change from the official side.
Does anybody have a workaround for this bug? Specifically, I would like to store and restore the window/frame/dialog at the previous location reliably on all platforms.
PS: My java installation is jdk1.8.0_102 for amd64 by Oracle on Ubuntu 16 Linux. Since I recently migrated from Windows to Ubuntu, I know that on Windows, the code above works as expected.
The adaptation to Swing using SwingWorker produces the same effect:
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingWorker;
public class GetBoundsBug extends JFrame implements ActionListener {
public static void main(String[] arg) {
GetBoundsBug myJFrame = new GetBoundsBug();
JButton myJButton = new JButton("Click here!");
myJButton.addActionListener(myJFrame);
myJFrame.setContentPane(myJButton);
myJFrame.setSize(300, 300);
myJFrame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent event) {
SwingWorker<Void, Void> mySwingWorker = new SwingWorker<Void, Void>() {
#Override
public Void doInBackground() {
Rectangle myRectangle = getBounds();
myRectangle.y--;
setBounds(myRectangle);
myRectangle.y++;
setBounds(myRectangle);
return null;
}
};
mySwingWorker.execute();
}
}
Well, in the original bug database entry this is marked as "Won't fix" and explained as a quirk in the window manager, rather than the JDK.
What window manager are you using?
Just an additional note. I noticed that your code failed to do very much on the Event Dispatch Thread. All of Java's drawing APIs are single threaded by design, meaning that your application should not be expected to work correctly unless you dispatch GUI updates to the Event Dispatch Thread.
This means you need to (in your main) create a new Runnable that when evaluated will present your widgets, and submit that to the EDT.
Also, your action listener updates the component state within the action, bypassing the repaint request and ignoring the typical safeties required to ensure dispatch to the EDT.
In both of these ways, you code is not valid GUI code in a Java environment, and the bug that you identify may have nothing to do with your behavior, as your program is violating the GUI toolkit design before you even know if the bug impacts it.
Also, awt only wraps components. If the components lie, then the lie trickles into Java. Not much can be done about that (but I no longer think it's the primary thing to worry about). If you don't like that, use Swing, which is a much more sane / stable environment.
I have a working application, which working fine in Java 1.6 and 1.7 and even 1.8 update 31. I just update my Java today 1.8 update 45 and found my application interface having issue. For an example:
This is my working application screen. This is what it should be, but after the update its become like this (below):
Once I get the not functioning interface, I need to click on the area or I need to minimize the application and open again to revert back to normal.
Code
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
tab.setTabPlacement(2);
frame.add(tab, BorderLayout.SOUTH);
ComparePanelMin cmp = new ComparePanelMin();
tab.add("Compare", cmp);
ReportPanelMin rp = new ReportPanelMin();
tab.add("Reporting (For Single Compare)", rp);
ChangeListener changeListener = new ChangeListener() {
#Override
public void stateChanged(ChangeEvent changeEvent) {
idx = tab.getSelectedIndex();
}
Above code to switch between the tabs. Any advice or reference links is highly appreciated.
EDITED
DeadLock
I guess its an issue of deadlock I faced a similar issue of GUI freezing with Swing. Nothing worked out so I had to dig into the code of Swing and I found some really crappy codes which were causing the dead lock and it was very difficult to trace even in the thread dump.
you can try these tools and check for dead lock
http://docs.oracle.com/javase/7/docs/technotes/guides/management/jconsole.html
https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jvisualvm.html
you can search how to identify dead lock using these tools
Also the way you're adding tab in frame is not the right way you should add it using frame.getContentPane().add(tab, BorderLayout.SOUTH)
I have seen similar issues if not all Swing components are created on the event dispatch thread (EDT).
Make absolutely sure that even your initial JFrame is created/shown from the EDT:
public class HelloWorldSwing {
private static void createAndShowGUI() {
JFrame frame = new JFrame("Hello Swing");
// Your init code here...
frame.setVisible(true);
}
public static void main(String[] args) {
// Schedule creation of UI on the EDT
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}