I have long text in Text Area placed to the Scroll Pane. I've noticed that when I rotate the mouse wheel, the text is redrawn severely, maybe even entirely.
This is the demo app:
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class TextArea {
public static void main(String[] args) {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JTextArea textArea = new JTextArea();
textArea.setColumns(80);
textArea.setRows(20);
textArea.setLineWrap(true);
final JScrollPane scrollPane = new JScrollPane(textArea);
textArea.append("1234567890 ".repeat(20000)); // Java 11
frame.add(scrollPane);
frame.pack();
frame.setVisible(true);
}
}
Redrawing can be easily detected if you place a logging breakpoint to the sun.java2d.SunGraphics2D.drawString(String, float, float) method. For me, it logs a couple of thousands hits when I rotate mouse wheel by a single unit (the number of hits depends on the size of frame). If I stop at breakpoint, I see that y position of the string to draw differs a lot and the difference is much more than the height of my screen.
I think it should better redraw only visible lines, or maybe even newly appeared lines.
Can JScrollPane be set up somehow to optimize the amount of draw calls? Or is it an unoptimized thing in Swing?
When I run this code and spin the mouse scroll wheel, the GUI doesn't flicker or change at all. The only reason I see my scroll wheel doing something is the JScrollPane tab moves upward.
I compiled to the Java 8 standard, using Java 14.0.2. My computer runs on Windows 10.
Not surprising, since the text is identical.
Try this complete runnable code and see if it makes a difference.
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class LargeTextArea implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new LargeTextArea());
}
#Override
public void run() {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JTextArea textArea = new JTextArea();
textArea.setColumns(80);
textArea.setRows(20);
textArea.setLineWrap(true);
textArea.append("1234567890 ".repeat(20000)); // Java 11
final JScrollPane scrollPane = new JScrollPane(textArea);
frame.add(scrollPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
JTextArea indeed generates too much draw calls for a long line, seems like it redraws it fully and because of soft wrapping, it's split.
However, going deeper, it's visible that while scrolling, clipping area is set quite restrictively (to the newly visible space), so Graphics2D is able to skip drawing of all the strings that are outside of clipping.
So there is no need to worry because actually not much drawing should be performed.
Related
Working with the JTreeWithScrollbar example, but scaled it back significantly to focus on the issue.
The original code would have the vertical scrollbars appear as needed.
Here, there is plenty of space and no scrollbars are needed.
If the panel is moved enough, the scrollbar will appear.
Once the following line of code was added, the scrollbars stopped appearing.
tree.setUI(new MyTreeUI());
Notice no scrollbar.
If the above line of code is commented out, the vertical scrollbar appears.
Checking the documentation for BasicTreeUI and there isn't anything related to showing/hiding scrollbars.
2 Questions
1 - When utilizing the BasicTreeUI object, what is required to ensure the scrollbars still function?
2 - Why is it the Horizontal scrollbar never appears even if the line of code is commented out?
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.plaf.basic.BasicTreeUI;
import javax.swing.tree.DefaultMutableTreeNode;
import java.awt.Dimension;
public class JTreeWithScrollbar extends JPanel {
private JEditorPane htmlPane;
private JTree tree;
public JTreeWithScrollbar()
{
//Create the nodes.
DefaultMutableTreeNode top = new DefaultMutableTreeNode("The Java Series");
DefaultMutableTreeNode book1Node = new DefaultMutableTreeNode("Book 1");
DefaultMutableTreeNode book2Node = new DefaultMutableTreeNode("Book 2");
top.add(book1Node);
top.add(book2Node);
tree = new JTree(top);
tree.setUI(new MyTreeUI()); ///Comment out this line of code and the vertical scrollbar appears.
JScrollPane treeView = new JScrollPane(tree);
JScrollPane htmlView = new JScrollPane(htmlPane);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
splitPane.setTopComponent(treeView);
splitPane.setBottomComponent(htmlView);
Dimension minimumSize = new Dimension(100, 50);
htmlView.setMinimumSize(minimumSize);
splitPane.setDividerLocation(100);
splitPane.setPreferredSize(new Dimension(500, 300));
add(splitPane);
}
public static void main(String[] args)
{
//Create and set up the window.
JFrame frame = new JFrame("TreeDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel jp = new JPanel();
jp.add(new JTreeWithScrollbar());
frame.add(jp);
//Display the window.
frame.pack();
frame.setVisible(true);
}
private static class MyTreeUI extends BasicTreeUI
{
public MyTreeUI()
{
super();
}
#Override
protected void updateCachedPreferredSize() {
treeState.invalidateSizes();
tree.treeDidChange();
}
}
}
When utilizing the BasicTreeUI object, what is required to ensure the scrollbars still function?
As shown in the minimal example below, BasicTreeUI correctly shows each scroll bar when needed; resize the frame to see the effect.
Why does the horizontal scrollbar never appear even if the line of code is commented out?
After pack() the frame has been resized to adopt the preferred size of it content. Making the frame slightly smaller illustrates the effect. Your example adds the tree to a JPanel having a default FlowLayout which ignores preferred sizes; the example below adds the tree to the center of the frame's default BorderLayout which responds to preferred sizes.
I am assuming the updateCachedPreferredSize() must be doing other stuff behind the scenes…
Exactly. Each invocation of updateCachedPreferredSize() updates the component's preferred size to reflect any change in state (resize, expand, etc.); when the preferred size exceeds the viewport size, the scroll bars appear. As you observed, invoking super.updateCachedPreferredSize() allows normal operation, and any further customization must preserve that functionality.
In addition,
Expand rows as need like this.
Construct and manipulate Swing GUI objects only on the event dispatch thread.
Don't use setSize() when you really mean to override getPreferredSize() or illustrates a resize effect; more here.
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.plaf.basic.BasicTreeUI;
public class JTreeWithScrollbar {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
//Create and set up the window.
JFrame frame = new JFrame("TreeDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTree tree = new JTree(); //default model
for (int i = 0; i < tree.getRowCount(); i++) {
tree.expandRow(i);
}
tree.setUI(new MyTreeUI());
frame.add(new JScrollPane(tree));
//Display the window.
frame.pack();
frame.setSize(frame.getWidth() - 10, frame.getHeight() - 100);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
private static class MyTreeUI extends BasicTreeUI {
}
}
I have the following code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Main
{
public static void main(String[] args)
{
Window window = new Window("This is a title", 450, 350);
JButton buttonExit = new Button("Exit", 75, 25);
window.addElement(buttonExit);
window.build();
}
}
class Window // extend the current class
{
public Window window;
public JFrame frame;
public JPanel panel;
public String title;
// instantiate object with the constructor
public Window(String title, int width, int height)
{
this.frame = new JFrame(title);
this.frame.setPreferredSize(new Dimension(width, height));
this.frame.setLocationRelativeTo(null); // centers the main window relative to the center of the screen dimension
this.panel = new JPanel();
this.panel.setPreferredSize(new Dimension(width, height));
//this.panel.setLayout(new FlowLayout());
this.frame.add(panel);
}
public void build()
{
this.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.frame.pack(); // removes all unnecessary pixel space from the form
this.frame.setVisible(true);
this.frame.setSize(frame.getPreferredSize());
}
public void addElement(JButton element)
{
this.panel.add(element);
}
}
class Button extends JButton // extend the current class
{
public Button(String text, int width, int height)
{
JButton button = new JButton();
button.setPreferredSize(new Dimension(width, height));
button.setText(text);
button.setVisible(true);
new ButtonHandler(button);
}
}
class ButtonHandler implements ActionListener
{
public ButtonHandler(JButton button)
{
button.addActionListener(this);
}
public void actionPerformed(ActionEvent actionEvent) {
System.exit(0);
}
}
I have two problems with this:
The button is compressed and won't show its text
I cannot get the event handler to work and don't appear to get why
As a side note, I know that I don't specify a LayoutManager here, but I had this implemented before and it didn't solve my issue (I tried the FlowLayoutManager and the GridBagLayout [this would be my desired one, due to its flexibility]).
Can someone tell me, what I am doing wrong here? I've only worked with C# and WPF/WinForms before...
Issue 1:
Your custom Button class is-a JButton but also has-a JButton (named button) in the constructor.
The problem here is you install the ButtonHandler class to the button of the constructor, not the custom Button itself (which is referred to as this inside the constructor).
Issue 2:
When you set the [preferred] size of the JFrame property named frame (in the custom class named Window), you are not setting the frame's contents' [preferred] size, but the size of the whole JFrame, which includes the bar located at the top of the frame (which has the title of the frame).
That lets the contents of the frame to have a space less than the preferred size, because the preferred size is set to the whole frame.
I know, you are also setting the preferred size of the JPanel named panel, which is added to the frame, but when you pack the frame, then the preferred size of the frame is prioritized rather than the preferred size of the contents of the frame, so that's probably why you are seeing the button compressed.
Let me demonstrate what I mean, with a bit of code:
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TestFramePrefSz {
public static void main(final String[] args) {
SwingUtilities.invokeLater(() -> {
final JFrame frame = new JFrame("Testing JFrame preferred size");
final JPanel contents = new JPanel();
contents.setPreferredSize(new Dimension(200, 200));
frame.setPreferredSize(new Dimension(200, 200));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(contents);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
System.out.println(contents.getSize());
});
}
}
As you can see, the dimension object printed (which is the actual size of the panel) is about 184x161 rather than 200x200 requested, because the preferred size of the frame is also set to 200x200 (which includes the title of the frame etc...).
The solution, is to only set the preferred size of the contents, not the frame (in this particular scenario at least).
So you should:
Remove the line this.frame.setSize(frame.getPreferredSize()); inside the build method.
Remove the line this.frame.setPreferredSize(new Dimension(width, height)); inside the constructor of the custom class named Window.
Issue 3:
The line this.frame.setLocationRelativeTo(null); inside the constructor of the custom class named Window, is not effective in that place.
Imagine that, when you call this method, it has to determine the location of the frame to set it.
So it needs to know first of the size of the screen and then the size of the frame itself.
But what is the size of the frame at the point where you call this method? It is about 0x0. Not the preferred size as you might expect.
That makes the calculation of the frame's location to be such that the frame will not be centered at the screen.
That's because the preferred size is a property of the frame, which is a different property than the size.
So you either have to setSize prior making the call, or better to set the preferred size of the contents of the frame (ie this.panel), then call pack on the frame and finally call the method this.frame.setLocationRelativeTo(null).
Then you are free to set the frame to visible to see where it is located in the screen (ie should be centered).
So the solution is to follow a pattern like the following:
Create the frame, add the contents of the frame to it and set the contents' preferred size.
Call pack on the frame (remember this call will change the size of the frame, according to the preferred sizes of the contents of the frame or the frame's itself).
Call setLocationRelativeTo(null) on the frame.
Call setVisible(true) on the frame.
If you take a look at your code, you are instead doing:
Create the frame.
Set the preferred size of the frame.
Call setLocationRelativeTo(null) on the frame (but the size of the frame is not set yet).
Add the contents of the frame to it (ie the panel).
Call addElement which adds more content to the panel.
Call pack on the frame (remember the preferred size of the frame is set up to this point, so it will override any other preferred sizes, such as the contents' preferred size).
Call setVisible(true) on the frame.
Call setSize on the frame, with the preferred size of it. So you are overwriting the size the frame has had from step 6.
I don't know what you're using as a tutorial. I recommend the Oracle tutorial, Creating a GUI With JFC/Swing. You can skip the Netbeans section, but I recommend going through the rest of the sections.
I created the following GUI.
The Exit button works, disposing of the GUI. The X in the upper right also disposes of the GUI.
Here's the runnable example code. The explanation follows the code.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class JButtonExample implements Runnable{
public static void main(String[] args) {
SwingUtilities.invokeLater(new JButtonExample());
}
private JFrame frame;
#Override
public void run() {
frame = new JFrame("This is a title");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
exitProcedure();
}
});
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setPreferredSize(new Dimension(300, 200));
panel.setBorder(BorderFactory.createEmptyBorder(
75, 100, 75, 100));
JButton button = new JButton("Exit");
button.addActionListener(new ExitListener(this));
panel.add(button, BorderLayout.CENTER);
return panel;
}
public void exitProcedure() {
frame.setVisible(false);
frame.dispose();
System.exit(0);
}
public class ExitListener implements ActionListener {
private JButtonExample example;
public ExitListener(JButtonExample example) {
this.example = example;
}
#Override
public void actionPerformed(ActionEvent event) {
example.exitProcedure();
}
}
}
I make a call to the SwingUtilities invokeLater method from the main method. This method makes sure that the Swing components are created and executed on the Event Dispatch Thread.
I separate the JFrame code from the JPanel code. This is so I can focus on one part of the GUI at a time.
The JFrame methods have to be called in a specific order. This is the order that I use for most of my Swing applications.
The WindowListener (WindowAdapter) gives my code control over the closing of the JFrame. This will allow the Exit button actionListener to close the JFrame. A WindowListener is not a simple concept.
The JFrame defaultCloseOperation is usually set to EXIT_ON_CLOSE. In order for the WindowListener to work, I had to set the defaultCloseOperation to DO_NOTHING_ON_CLOSE.
I let the JFrame determine its own size by using the pack method.
I set the preferred size of the JPanel.
I created an empty border for the JPanel, so the JButton would expand to fill the rest of the JPanel. That's what happens to the component placed in the center of a BorderLayout.
I created an ExitListener class. Because it's an inner class, I didn't have to create a constructor or pass the JButtonExample instance. I created a constructor so you can see how it's done, and how the actionListener method can execute the exitProcedure method of the JButtonExample class.
I hope this JButton example is helpful. The WindowListener is a bit advanced for a simple example, but you can see how it's done.
this is my first question on stackoverflow so pls don't be so hard with me (and my English), I'll try my best asking a good question.
The problem is about what the title suggests -> setting the background of a JTextpane (specifically setting it transparent). As the setBackground-method takes a color argument, the way i went was with an alpha value = 0. This leads to the following visual artifacts:
example picture of the visual artifacts when running the code below
I will describe it in detail now, say what i've already tried and then post a minimal example for everyone to be able to recreate the bug easily.
I have a JFrame (myFrame) holding a JPanel (Test()) in which i paint. The background of this JPanel is set to green as you can see in the code. I did this to differ between the background of the TextPane and the actual background of the panel.
We also have a JTextPane inputfield -> which takes user input (it displays what you write). This is held by a JScrollPane scrollpane.
So the Target (meaning what i try to achieve): is a User input field, which is transparent, but still displays the text the user puts in. I tried to achieve this by setting the background of the inputfield and the scrollpane to a transparent color.
I would really appreciate it, if you don't just type something like (you need to setOpague(false) for ....) if you don't know exactly what you're talking about, because i nearly tried everything i can think of and read every post i could find in the internet about the problem. I will post some of them at the end. So...
What i already tried:
The usual way i found while searching for something like "How to make TextPane transparent" was to setOpague(false) at itself as well as the scrollpane and the viewport of the scrollpane. 1. Reading about what the method actually does i don't think that is a proper solution. 2. setting Opague(false) on these three leads to everything being invisible so, that's not good. Packing the frame again after setting the background. Either nothing was fixed or the components became completely invisible.
I also tried: setBackground(null), setting the Background of just the inputfield (just every single component and every possible combination amongst the three (scrollpane, viewport, inputfield)), mixing setOpague(true)/setOpague(false)/setBackground(...) in every way i could think of. Overriding the paintComponent method of the textpane and scrollpane seemed like a good approach, but i did not come very far with it.
So here is the code:
public class Test extends JPanel {
JTextPane inputField = new JTextPane();
JScrollPane scrollpane = new JScrollPane(inputField);
#Override
public void paint(Graphics g) {
super.paint(g);
inputField.setBounds(10,10,100,100);
scrollpane.setBounds(10,10,100,100);
}
public Test(){
this.setOpaque(true);
this.setBackground(Color.GREEN);
inputField.setBounds(10,10,100,100);
scrollpane.setBounds(10,10,100,100);
inputField.setBackground(new Color(0,0,0,0));
scrollpane.setBackground(new Color(0,0,0,0));
scrollpane.getViewport().setBackground(new Color(0,0,0,0));
this.add(scrollpane);
}
public static void main(String[] args) {
JFrame myFrame = new JFrame();
myFrame.add(new Test());
myFrame.pack();
myFrame.setSize(640,480);
myFrame.setPreferredSize(new Dimension(640,480));
myFrame.setVisible(true);
}
}
And here some links to posts I read which describe similar problems:
Java - Transparent JScrollPane
Transparent JEditorPane in a JScrollPane over a background JPanel
setOpaque(true/false); Java
I would really appreciate if someone can help me with the problem or even only suggest me an alternative solution. I'm writing a little chat-program atm for a project for my university and i think transparent message fields are a neat idea. I will try to answer here as fast as i can. Thx in advance.
Do not use transparent color as background - kind of hard to delete with it (e.g. when component is being repaint (and opaque)).
Do not use setBounds (unless using null LayoutManager). In below example I used setPreferredSize but still better to correctly use LayoutManager (I am a bit lazy, and lot of work to do at the moment).
public class Test extends JPanel {
JTextPane inputField = new JTextPane();
JScrollPane scrollpane = new JScrollPane(inputField);
public Test(){
this.setOpaque(true);
this.setBackground(Color.GREEN);
inputField.setPreferredSize(new Dimension(300, 100));
inputField.setOpaque(false);
scrollpane.setOpaque(false);
scrollpane.getViewport().setOpaque(false);
this.add(scrollpane);
}
public static void main(String[] args) {
JFrame myFrame = new JFrame();
myFrame.add(new Test());
myFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
myFrame.setPreferredSize(new Dimension(640,480));
myFrame.pack();
myFrame.setVisible(true);
}
}
The whole code of main should be called on the EDT (e.g. SwingUtilities.invokeLater) since it is manipulating swing components but that is not part of the question (and not that relevant here since setVisible is the last command - components not being displayed while changed).
Your program gave me some errors when launching, occasionally. Make sure to run a swing GUI from the EDT (invokeLater()).
The line that is causing your issue is:
scrollpane.getViewport().setBackground(new Color(0,0,0,0));
Also - is there some reason you are setting bounds manually instead of using a layout manager?
Maybe I didn't understand your question, or you want to have an image in the background - but could you not just set the color of your text area to be the same color as your JPanel?
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
public class Test extends JPanel {
JTextPane inputField = new JTextPane();
JScrollPane scrollpane = new JScrollPane(inputField);
public Test(){
this.setBackground(Color.GREEN);
scrollpane.setPreferredSize(new Dimension(300, 300));
inputField.setBackground(Color.GREEN);
this.add(scrollpane);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame myFrame = new JFrame();
myFrame.add(new Test());
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setPreferredSize(new Dimension(640,480));
myFrame.pack();
myFrame.setVisible(true);
}
});
}
}
If I add an instance of WorldWindowGLJPanel to my JFrame then remove it and add it again, the panel's GL viewport gets recalculated to a Rectangle that is much smaller than the available space. The dimension appears to consistently be 116x26. What this means is the frame becomes mostly blank with just a small piece of the WorldWind panel displaying in the bottom left corner of the frame. Resizing the frame appears to reset the viewport but is there a way to reset the viewport programmatically?
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import gov.nasa.worldwind.Model;
import gov.nasa.worldwind.WorldWind;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.awt.WorldWindowGLJPanel;
public class WorldWindTest {
public static void main(String[] args) {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final WorldWindowGLJPanel wwPanel = new WorldWindowGLJPanel();
Model wwModel = (Model) WorldWind.createConfigurationComponent(AVKey.MODEL_CLASS_NAME);
wwPanel.setModel(wwModel);
JPanel buttons = new JPanel(new FlowLayout());
buttons.add(new JButton(new AbstractAction("Re-add WorldWind panel") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
frame.getContentPane().remove(wwPanel);
frame.getContentPane().add(wwPanel);
frame.getContentPane().repaint();
}
}));
frame.getContentPane().add(buttons, BorderLayout.NORTH);
frame.getContentPane().add(wwPanel);
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.setVisible(true);
}
});
}
}
4 and half years late to the party, but posting my solution because I couldn't find one when I ran into this issue.
This problem seems to have nothing to do with WorldWindowGLJPanel, I believe it's a problem with any GLJPanel.
When you remove the GLJPanel from its parent, it resets its internal pixel scaling to some sentinel values. That's why it becomes tiny, but continues to (sorta) work.
The following 3 lines of code fixed it for me (I add them to a hierarchy listener and call them when the parent changes, but you can add them to the SSCCE above in the button handler)
wwPanel.initializeBackend(false);
wwPanel.reshape(0, 0, 0, 0);
wwPanel.revalidate();
initializeBackend tells OpenGL to initialize the backend, if it isn't initialized (Not 100% sure what causes it, but it seems to be tied to moving between parent windows).
Reshape will overwrite those pixel scale sentinel values, and so it'll actually calculate the proper size to display.
Revalidate causes it to recalculate the size of the panel, which I believe kicks off the size calculations now that those sentinel values aren't in the way.
Recently every single one of my apps that extends JFrame fails to actually show the frame. The program will run and then will terminate after about 8 seconds without ever showing anything and without an error message. This happens for all the programs I've made in the past as well as any new programs.
For testing purposes I am using the basic example from the oracle documentations.
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class test extends JFrame{
public static void main(String[] args){
//1. Create the frame.
JFrame frame = new JFrame("FrameDemo");
//2. Optional: What happens when the frame closes?
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//3. Create components and put them in the frame.
JLabel emptyLabel = new JLabel();
frame.getContentPane().add(emptyLabel, BorderLayout.CENTER);
//4. Size the frame.
frame.pack();
//5. Show it.
frame.setVisible(true);
}
}
I am using eclipse and I've already tried switching workplaces.
I've looked at existing threads and found nothing that wasn't due to coding errors.
How can i solve this?
EDIT: The program doesn't output anything from System.out.println() after this line:
JFrame frame = new JFrame("FrameDemo");
It outputs anything before that.
Alright so I checked your code and it works.
First things first, your JLabel isn't visible if it doesn't have anything in it.
pack();
//basically CRUSHES the entire frame if it doesn't have objects to collapse on.
Also, if you don't want to put anything in your JLabel, don't pack it yet. Just set it to a certain size with
frame.setSize(width,height);
It only shows nothing because you collapsed it without putting anything in the JLabel. I hope I answered your question basically this is what you want
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class test extends JFrame{
public static void main(String[] args){
//1. Create the frame.
JFrame frame = new JFrame("FrameDemo");
//2. Optional: What happens when the frame closes?
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//3. Create components and put them in the frame.
JLabel emptyLabel = new JLabel("BLAHBLAHBHALBAHLKKDJF");
frame.getContentPane().add(emptyLabel, BorderLayout.CENTER);
//4. Size the frame.
frame.pack();
//5. Show it.
frame.setVisible(true);
}
}
Or you could just set size with
frame.setSize(width,height);
Have fun!