I have a slightly complicated JavaFX GUI with the following component structure (simplified) as shown below. You will see that a SwingNode is used to contain the main bulk of the application, but I cannot tell you the design principle behind this since I didn't write the original code.
I am aware of various cautions about occasional odd behaviour when Swing & JavaFX are mixed, but there isn't the time at present to re-write the UI. The application is built to run on a Windows 7/8/10 platform, and what I'm seeing is as follows:
(a) On three different platforms I've tested (Windows XP native, Windows 7 VM, Windows 8 VM, different size monitors), when the application's Windows "maximize" decoration is clicked, the application resizes OK (by which I mean it is slightly jumpy and delayed, but the actual repainting to fill the screen is done correctly).
(b) However, on one further platform, the 'maximize' causes the entire content of the Stage to go white, and doesn't repaint properly until, say, a menu or one of its items is clicked. The machine in question is a Dell Optiplex 64-bit Windows 7 Pro SP1 with a DVI monitor of 1920 x 1080 sourced from an Intel HD Graphics 4600. ClearType is set to ON, and the version of Java is 1.8.0_73_b02.
There is one further question on SO regarding this issue, but it was created in June 2015 and never answered, so I'm not sure what to think.
Has anyone else come across this issue and/or feels able to comment on what might be causing it ? Is there some sort of 'revalidate/repaint' code, or JavaFX equivalent, which might be worth me trying as a workaround ?
public class Main extends Application
{
private SwingNode mainSwingNode = new SwingNode();
private JPanel mainPanel = new JPanel();
public void start(Stage primaryStage) throws Exception
{
BorderPane parent = new BorderPane(mainSwingNode);
Scene scene = new Scene(parent, 1024, 768);
// Build Swing components
SwingUtilities.invokeLater(() ->
{
createAndShowGUI();
mainSwingNode.setContent(mainPanel);
});
primaryStage.setScene(scene);
primaryStage.show();
}
public void createAndShowGUI()
{
mainPanel.setLayout(new BorderLayout());
// Setup canvas area & canvas rulers
mCanvasTabbedPane.setPreferredSize(new Dimension(800,600));
mainPanel.add(mCanvasTabbedPane, BorderLayout.CENTER);
menubar.initForActionsMap(menuActionsMap);
// Listen for property changes for site to enable/disable menus
ProjSingleton.getInstance().addPropertyChangeListener(menubar);
mainPanel.add(menubar, BorderLayout.NORTH);
// Setup show/hide sidebar button
btnShowSidebar = new JButton(menuActionsMap.get(ShowSidebarAction.class));
menubar.add(Box.createHorizontalGlue());
menubar.add(btnShowSidebar);
btnShowSidebar.setOpaque(false);
btnShowSidebar.setAlignmentX(JComponent.RIGHT_ALIGNMENT);
btnShowSidebar.setBorder(new EmptyBorder(new Insets(2,2,2,2)));
// Add site manager toolbar
sidebar.setLayout(new GridLayout(2, 0));
sidebar.setAlignmentX(JComponent.RIGHT_ALIGNMENT);
sidebar.add(siteManagementPanel);
sidebar.add(new JScrollPane(layerManagerView));
mainPanel.add(sidebar, BorderLayout.EAST);
Main.statusBar = new StatusBar();
Main.statusBar.setCanvasTabbedPane(mCanvasTabbedPane);
mainPanel.add(Main.statusBar, BorderLayout.SOUTH);
mainPanel.setVisible(true);
}
....
....
}
Related
I am trying to make a JTabbedPane in Java 7 on OSX that has tabs positioned to the left with their text horizontal (instead of vertical). However, with the code:
import javax.swing.*;
import java.awt.Dimension;
class Probs extends JDialog {
JTabbedPane options = new JTabbedPane();
Probs(JFrame owner) {
//main constructor
super(owner, "User Preferences", true);
//set the tabs to be left aligned
options.setTabPlacement(JTabbedPane.LEFT);
//construct the authorization panel
JPanel authorization = new JPanel();
authorization.add(new JLabel("test"));
options.addTab("test", authorization);
add(options);
setSize(new Dimension(300,300)); //should use pack here
setResizable(false);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
JFrame test = new JFrame();
new Probs(test);
test.dispose();
}
}
I get a dialog box which looks like: this image
I would like the tab text to be horizontal (the 'test' title on the tab be oriented horizontally instead of vertically).
I searched around on Google for a while and have only run into occurrences wherein people wanted to achieve vertical text on their tabs, I could not manage to locate any in which people wanted to have horizontal text (what I am trying to achieve).
In particular, I am trying to achieve something which exactly looks like the image mentioned in the first post of this question. It is basically the exact opposite of that question because the person in that tab started with what I am trying to achieve (I believe). Basically, I am trying to determine how to create the image displayed in the first post of that question.
Can someone please tell me how to have left-oriented tabs while preserving horizontal tab titles (as opposed to vertical)?
Thank you for your time and assistance.
Again, since I can't replicate the problem, Try this suggestion:
JPanel authorization = new JPanel();
authorization.add(new JLabel("test"));
options.addTab("", authorization);
JLabel labTab2 = new JLabel("test"); // create a label
options.setTabComponentAt(0, labTab2); // set it to the component
The alignment is determined by your operating system. If you want to change the alignment of the tab text, you have to change the look and feel of your swing application. This worked for me. See here.
The system look and feel at MacOSX didn't support what you want in JTabbedPane. You must create a customized JComponent to do this or to set the look and feel of your application to cross platform (java metal) as stated before by #MonkeySupersonic.
I suggest the readings:
Apple Java Development Guide (section: User Interface Toolkits for Java) - https://developer.apple.com/library/content/documentation/Java/Conceptual/Java14Development/04-JavaUIToolkits/JavaUIToolkits.html
mac User Interface Guidelines - https://developer.apple.com/macos/human-interface-guidelines
I have an applet I have written that has a JLabel (containing an ImageIcon) and a custom ImagePanel inside a JPanel. For some reason the JLabel NEVER shows up in safari and firefox on mac os on first run/load but on other OSes (windows,linux) it appears fine. Now in the same applet there's a button that flips the image to another image. On safari/firefox on mac os, when the button is clicked, the second image shows, the when clicked again, the first image now appears!! Any idea what could be causing this issue? Even on safari for windows the applet works fine.. i.e. first image loads and appears.
UI code
public void createUI(){
mainpanel = new JPanel();
mainpanel.setMaximumSize(new Dimension(154, 212));
mainpanel.setMinimumSize(new Dimension(154, 212));
mainpanel.setName("mainPanel");
mainpanel.setLayout(new BorderLayout());
lcdpanel = new ImagePanel(bgLcdImage);
lcdpanel.setBounds(22, 22, 110, 28);
bgImage = Toolkit.getDefaultToolkit().createImage(bytes);//BufferedImage
label = new JLabel(new ImageIcon(bgImage));
mainpanel.add(lcdpanel);
mainpanel.add(label);
mainpanel.invalidate();
getContentPane().add(mainpanel);
repaint();
}
Button click code
private void flipImage()
{
label.setIcon(new ImageIcon(backImg));
label.repaint();
lcdpanel.setVisible(false);
lcdpanel.repaint();
mainpanel.repaint();
this.repaint();
}
Any help would be appreciated.Thanks
I even made the jlabel as a imagepanel, set the layout of jpanel to null
Setting the layout to null is the worst thing you can do. That will generally cause more problems than solve a problem.
The issue is not where i want the jlabel to be shown but WHY its not showing on Mac OS X firefox/safari browsers when it shows on windows/linux firefox/safari browsers.
How do we know when only a few lines of code are posted? Post a proper SSCCE when you have a problem.
On safari/firefox on mac os, when the button is clicked, the second image shows, the when clicked again, the first image now appears!!
The general format when adding/removing components on a visible GUI is to do:
panel.add(...);
panel.revalidate();
panel.repaint(); // sometimes needed
You never need to invoke repaint when you change the property of a component. Swing is smart enough to do the repaint for you.
label.setIcon(new ImageIcon(backImg));
//label.repaint();
Good day everyone.
First of all: check this image.
Please note that in the first of the 3 frames, the button is styled with Metal Look and Feel, but the frame is Windows styled. The other 2 frames are "OK" in the sence that the button LAF matches the frame LAF.
The code for all of these (same order as the images):
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.getContentPane().add(new JButton("button"));
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setUndecorated(true);
frame.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
frame.setSize(100, 100);
frame.getContentPane().add(new JButton("button"));
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
// 0 => "javax.swing.plaf.metal.MetalLookAndFeel"
// 3 => the Windows Look and Feel
String name = UIManager.getInstalledLookAndFeels()[3].getClassName();
UIManager.setLookAndFeel(name);
} catch (Exception ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame();
frame.getContentPane().add(new JButton("button"));
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
Now what bothers me is that I have never been forced to use the lines frame.setUndecorated(true); frame.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);, as setting the Look and Feel just worked with the UIManager.setLookAndFeel() method. Normally, the JFrame itself would get styled too, but this seems not longer the case as I get a Windows styled frame (1st image, 1 code snippet).
Why is this? Is this new in Java 7? This seems really weird.
Normally, without touching code that involves Look and Feel, the program should start with the Metal Look and Feel, as this is the standard Java Look and Feel. So why does the first program start with a Windows frame?
Add this line in your main method before you init the JFrame
JFrame.setDefaultLookAndFeelDecorated(true);
I noticed the same thing a while ago when I started using substance but that line is all it took to fix it.
As the preceding code snippet implies, you must invoke the setDefaultLookAndFeelDecorated method before creating the frame whose decorations you wish to affect. The value you set with setDefaultLookAndFeelDecorated is used for all subsequently created JFrames. You can switch back to using window system decorations by invoking JFrame.setDefaultLookAndFeelDecorated(false). Some look and feels might not support window decorations; in this case, the window system decorations are used.
That's from Oracle in reference to that line of code.
This is a feature of Java, by default JFrame Window borders will not be decorated, but using the mentioned function allows the set look and feel to decorate the Window. This feature was implemented in 1.4 from what I can tell.
Edit:
Also, if you want to apply your custom look and feel to JDialog window borders, you can use the same static method on the JDialog class in the same place you called it on JFrame:
JDialog.setDefaultLookAndFeelDecorated(true);
I'm guessing that you hane not set the swing.defaultlaf system environment variable, but maybe you could check if your swing.properties is present and if it contains an entry swing.defaultlaf. This could be the reason, see below for how the UIManager chooses L&F.
I have the file present on my MacBook, obviously, as Apple wants the Apple L&F to be the default. But I have not checked a Windows machine yet..
Here's an excerpt from the Java 7 documentation which has been pretty much unchanged since Java 1.4. Java 1.4.2, Java 1.5, Java 6, Java 7:
Default look and feel
The class used for the default look and feel is chosen in the following
manner:
If the system property swing.defaultlaf is
non-null, use its value as the default look and feel class
name.
If the Properties file swing.properties
exists and contains the key swing.defaultlaf,
use its value as the default look and feel class name. The location
that is checked for swing.properties may vary depending
upon the implementation of the Java platform. In Sun's implementation
the location is ${java.home}/lib/swing.properties.
Refer to the release notes of the implementation being used for
further details.
Otherwise use the cross platform look and feel.
I'm trying to get a basic Swing Application to run on my Mac OS X 10.8.2 (Java version 1.6.0_37) machine, and every time I try to run it from Eclipse, the frame appears, but I can't interact with it.
I've tried to start from a basic, clean slate where I create a new Swing Application Window project in Eclipse (WindowBuilder->Swing Designer->Application Window). This generates the following skeleton code:
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.BorderLayout;
public class Test {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Test window = new Test();
window.frame.setVisible(true);
window.frame.pack();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Test() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btnPress = new JButton("Press");
frame.getContentPane().add(btnPress, BorderLayout.CENTER);
}
}
Everything seems to be fine, but when I run this from Eclipse, the frame doesn't let me interact with any components (in my non-example code, there are buttons and tabs).
Also, in the console, I see things like:
2012-11-09 14:30:27.624 java[8107:707] [Java CocoaComponent compatibility mode]: Enabled
2012-11-09 14:30:27.626 java[8107:707] [Java CocoaComponent compatibility mode]: Setting timeout for SWT to 0.100000
Is there some Mac-specific setting that I have to change? (I'm using the latest default Mac JRE)
The program runs fine on my machine under OSX, but it could be the missing
window.frame.pack();
Have you tried this?
Test window = new Test();
window.frame.pack();
window.frame.setVisible(true);
I had the same problem when using the DJ Swing library in my application (it uses SWT). Interestingly, the problem occurred even though I didn't initialise DJ Swing explicitly. It now works because I have added DJ Swing initialisation:
public class SwingAppTest {
public static void main(String[] args) {
NativeInterface.open();
UIUtils.setPreferredLookAndFeel();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Example");
frame.getContentPane().setLayout(new BorderLayout());
frame.setPreferredSize(new Dimension(400, 200));
frame.setBounds(0,0,200,200);
frame.setTitle("blah");
JButton blah = new JButton("blah");
blah.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("button clicked");
}
});
frame.getContentPane().add(blah, BorderLayout.CENTER);
frame.setVisible(true);
}
});
NativeInterface.runEventPump();
}
}
Apple is no longer supporting Java in is operating systems after 10.6:
Apple not committing to Java support in Mac OS X 10.7
seems like missing or incompatible library files in the JRE.
that is weird. I tried your sample (no linux) and don't see any problem there.
So as Wayne mentioned, might be macos issue.
Btw, what is your java version you're using?
On the other hand problem might be in the code you didn't share with us => hard to guess :)
EDIT: OK, so it seems you're playing "guess what I have in my code" game with us :) As my assumption is that code not shown causes problem.
It reminds me of some of these Poiroit/Agatha Christie detective stories, where just a little detail might have significant impact on the reality.
This is the reason for my theory:
code shown uses Java swing library (import javax.swing. ...) + Awt (import java.awt. ...) - this combonation is a common use case, however
the error message you shared shows SWT library error (Setting timeout for SWT to 0.100000)
So to me it seems like you're mixing things that should never be mixed.
As Swing is java UI library that is completely OS independent (originally Sun made) that is built on top of Awt. However SWT is completely different java UI library which is kind of mix of native calls with java on it (originally IBM made).
Therefor I'd suggest to double check your code and make sure that if you use JFrame, the only library components you have there are from Swing (javax.swing....) / Awt (java.awt. ...).
I've been knocking my head against a wall for days trying to get this working and finally found the answer:
'It's solved now - it was just a case of removing swt.jar from the project dependencies.'
Hey presto!!!!
In my case, I was trying to code a game where I used jPanel. I needed to override the paint method and added pack(); to the main and it finally showed me what I was trying to draw.
I keep telling myself that this should be simple, and yet I'm completely lost. Let me start by saying that I'm new to NetBeans IDE, and that I am using it out of necessity. I don't really know much about it yet.
I have successfully designed my main window for my application. The right side of the application is essentially a large window into a three-dimensional space that visualizes certain transforms on data sets. I have searched through the palette and the palette manager and even tried to add the Canvas3D component to the palette manually from a JAR, but I still can't get it.
I would really like to be able to drag and drop this component into my application, and intuitively, it seems possible. I'm on Mac OS X; the output from my About NetBeans tells more.
Product Version: NetBeans IDE 6.7 (Build 200906241340)
Java: 1.5.0_19; Java HotSpot(TM) Client VM 1.5.0_19-137
System: Mac OS X version 10.5.7 running on i386; MacRoman; en_US (nb)
Userdir: /Users/dremelofdeath/.netbeans/6.7
Thanks in advance for helping me out -- I really appreciate it.
The Canvas3D is a heavyweight component meaning it uses a native peer component to hook into DirectX or OpenGL so probably this kind of component is not available for drag and drop. Though you could try extending a JPanel.
You can setup the layout manually quite easily using a BoderLayout.
MyFrame extends JFrame {
etc...
Container container = getContentPane();
container.setName("main.container");
container.setLayout(new BorderLayout());
container.add(new MyCanvasPanel(), BorderLayout.CENTER);
}
// this could probably be added to the palete
public class MyCanvasPanel extends JPanel {
SimpleUniverse su;
Canvas3D canvas3D;
public MyCanvasPanel() {
canvas3D = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
add("Center", canvas3D);
su = new SimpleUniverse(canvas3D);
}
}
Complete beginner guide:
Add a java.awt.Container to the JFrame. (Choose Beans\java.awt.Container).
Let the name of that container be canvasContainer.
Add a public variable to the class. (I assume the class name is MyJFrame)
public Canvas3D canvas3D;
The construction of the frame class is as follows:
public MyJFrame() {
initComponents();
}
Edit it as follows:
public MyJFrame() {
initComponents();
canvas3D = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
canvasContainer.add(canvas3D, "Center");
canvas3D.setSize(canvasContainer.getWidth(), canvasContainer.getHeight());
}
Add a listener to the Container when it is resized: (Often when the window is resized)
Choose the container \ Properties \ Events \ componentResized \ canvasContainerComponentResized
Type the following code:
if (canvas3D!=null)
canvas3D.setSize(canvasContainer.getWidth(), canvasContainer.getHeight());