JScrollBar + JTextPane with HTML not properly scrolling to maximum value - java

I have the following problem in a project of mine, took me a while to figure out whats causing the problem, and I can reproduce it with this simple code which I attached.
I am dynamically adding content to a JTextPane with a HTMLEditorKit. I set autoscroll to off because I want to control it manually (when user scrolled up, to stop, and when an event is triggered to get activated again).
The problem now is, when I set the value of the JScrollBar to it's maximum value, it's a different one, just the moment, after having content inserted to the HTMLDocument. When I trigger the setValue again a second time manually, it scrolls to the correct maximum value.
It seems the JScrollBar is not aware about the correct maximumValue just right after adding to the HTMLDocument, and just a (delayed) time later.
Using
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
is not a solution, because it also doesn't work properly. It doesn't scroll to the maximum value too, leaving a view pixel below, which I don't want.
Here is the full code reproducing the issue. If you click on the right button (add & scroll), it inserts a DIV element to the body. The moment the last visible line is reached, it doesn't scroll correctly to the last maximum value, the last line is hidden. But when you just click on the left button manually to trigger a second scrollToEnd(), it scrolls correctly to the maximum value.
Code:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package javaapplication26;
import java.io.IOException;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultCaret;
import javax.swing.text.Element;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
public class NewJFrame extends javax.swing.JFrame {
/**
* Creates new form NewJFrame
*/
public NewJFrame() {
initComponents();
this.setSize(500, 200);
this.setLocationRelativeTo(null);
this.jTextPane1.setEditorKit(new HTMLEditorKit());
this.jTextPane1.setContentType("text/html");
this.jTextPane1.setText("<html><body><div id=\"GLOBALDIV\"></div></body></html>");
this.jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
this.jScrollPane1.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
DefaultCaret caret = (DefaultCaret) this.jTextPane1.getCaret();
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
this.jScrollPane1.setAutoscrolls(false);
this.jTextPane1.setAutoscrolls(false);
}
private void scrollToEnd() {
this.jScrollPane1.getVerticalScrollBar().setValue(this.jScrollPane1.getVerticalScrollBar().getMaximum());
//this.jTextPane1.setCaretPosition(this.jTextPane1.getDocument().getLength());
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
jTextPane1 = new javax.swing.JTextPane();
jPanel2 = new javax.swing.JPanel();
jButton1 = new javax.swing.JButton();
jButton2 = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jPanel1.setLayout(new java.awt.BorderLayout());
jScrollPane1.setViewportView(jTextPane1);
jPanel1.add(jScrollPane1, java.awt.BorderLayout.CENTER);
getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);
jButton1.setText("Scroll to end");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
jPanel2.add(jButton1);
jButton2.setText("Add & scroll");
jButton2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton2ActionPerformed(evt);
}
});
jPanel2.add(jButton2);
getContentPane().add(jPanel2, java.awt.BorderLayout.PAGE_END);
pack();
}// </editor-fold>
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
try {
HTMLDocument doc = (HTMLDocument) this.jTextPane1.getDocument();
HTMLEditorKit editorKit = (HTMLEditorKit) this.jTextPane1.getEditorKit();
SecureRandom random = new SecureRandom();
String htmlCode = "<div style=\"background-color: #FFFF22; height: 12px; font-size: 12;\">"+new BigInteger(64, random).toString(64)+"</div>";
//editorKit.insertHTML(doc, doc.getLength(), htmlCode, 0, 0, null);
Element element = doc.getElement("GLOBALDIV");
if (element != null) {
doc.insertBeforeEnd(element, htmlCode);
}
this.scrollToEnd();
} catch (BadLocationException ex) {
Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
this.scrollToEnd();
}
/**
* #param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new NewJFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTextPane jTextPane1;
// End of variables declaration
}
This code replacement works though, but leaves a small gap, also not properly scrolling to the maximum value:
this.jTextPane1.setCaretPosition(0);
this.jTextPane1.setCaretPosition(this.jTextPane1.getDocument().getLength());

When you insert the div into the document, the document model is being updated immediately. However, the JTextPane only receives a notification that it is invalid and needs to be laid out. This notification creates an event on the EDT which is only processed after the current event (triggered by the button clicked) has finished.
Thus, at the moment when you invoke scrollToEnd(), the revalidation of the JTextPane is still pending, and the height of the text pane is still too small.
In order to get the sequence of events right, you need to schedule the invokation of scrollToEnd() in the EDT, by using invokeLater:
SwingUtilities.invokeLater(new Runnable(){
public void run(){
scrollToEnd();
}
});

Related

Why won't the JLabels or JButtons show up when running the GUI?

I have been playing around with numerous solutions but none of them seems to work. in the constructor, there is a default initComponents() which I can not change. So I created a second method called myComponents(). The class I am using extends JFrame so I do not need to create another frame in any initializer. I created a JPanel with a vertical Boxlayout, 2 labels, 1 text field, and 1 button. I added the panel to the frame then I added all the components to the panel then packed everything.
I am unsure as to why nothing shows up besides the frame when it is run.
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
/**
*
* #author gpbli
*/
public class MAINFRAME extends javax.swing.JFrame {
/**
* Creates new form MAINFRAME
*/
//MAINFRAME frame = new MAINFRAME();
JPanel homescreen = new JPanel();
JLabel numOfIngredLabel = new JLabel();
JTextField numOfIngred = new JTextField();
JButton okButton = new JButton();
JLabel logo = new JLabel();
ImageIcon img = new ImageIcon("logo_resized.png");
public MAINFRAME() {
initComponents();
myComponents();
}
public void myComponents(){
BoxLayout box = new BoxLayout(homescreen,BoxLayout.Y_AXIS);
homescreen.setLayout(box);
numOfIngredLabel.setText("How many Ingredients");
numOfIngred.setText("");
okButton.setText("OK");
logo.setText(" ");
logo.setIcon(img);
add(homescreen);
homescreen.add(logo);
homescreen.add(numOfIngredLabel);
homescreen.add(numOfIngred);
homescreen.add(okButton);
numOfIngredLabel.setVisible(true);
numOfIngred.setVisible(true);
okButton.setVisible(true);
logo.setVisible(true);
pack();
revalidate();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE)
);
pack();
}// </editor-fold>
/**
* #param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(MAINFRAME.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(MAINFRAME.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(MAINFRAME.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(MAINFRAME.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MAINFRAME().setVisible(true);
}
});
}
// Variables declaration - do not modify
// End of variables declaration
}
The appearance of initComponents() suggests the IDE is expecting the programmer to use the GUI builder, while the myComponents() is the programmer taking control of the GUI construction to code it by hand.
Use one or the other. I'd always use the latter, which does not require the JFrame to be extended. In fact, creating the main view of the GUI in a JPanel and adding that single component to a JFrame is the way we would typically recommend.
Note: See also the accepted answer to: Netbeans GUI editor generating its own incomprehensible code

Matisse vertical Flow Layout

Is there a way to create Netbeans Matisse Vertical Flow Layout like :
But Netbeans Matisse Flow Layout create like this :
FlowLayout will automatically "wrap" components whose width extends past the boundary of the container they're in. So, to accomplish what I think you're trying to accomplish, all you need to do is set the FlowLayout like you've done, and resize the JTextFields to the appropriate width.
Note: "what I think" was a pointed criticism of the fact that your question doesn't really help us know exactly what you're trying to accomplish.
Five JTextFields:
Notice if you resize one, it will "wrap" the others:
You can select and resize multiple components simultaneously:
I changed the widths to 250:
Viola:
Code:
public class NewJFrame2 extends javax.swing.JFrame {
/**
* Creates new form NewJFrame2
*/
public NewJFrame2() {
initComponents();
setSize(287,200);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jTextField1 = new javax.swing.JTextField();
jTextField2 = new javax.swing.JTextField();
jTextField3 = new javax.swing.JTextField();
jTextField4 = new javax.swing.JTextField();
jTextField5 = new javax.swing.JTextField();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
getContentPane().setLayout(new java.awt.FlowLayout());
jTextField1.setText("jTextField1");
jTextField1.setPreferredSize(new java.awt.Dimension(250, 20));
getContentPane().add(jTextField1);
jTextField2.setText("jTextField2");
jTextField2.setPreferredSize(new java.awt.Dimension(250, 20));
getContentPane().add(jTextField2);
jTextField3.setText("jTextField3");
jTextField3.setPreferredSize(new java.awt.Dimension(250, 20));
getContentPane().add(jTextField3);
jTextField4.setText("jTextField4");
jTextField4.setPreferredSize(new java.awt.Dimension(250, 20));
getContentPane().add(jTextField4);
jTextField5.setText("jTextField5");
jTextField5.setPreferredSize(new java.awt.Dimension(250, 20));
getContentPane().add(jTextField5);
pack();
}// </editor-fold>
/**
* #param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(NewJFrame2.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(NewJFrame2.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(NewJFrame2.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(NewJFrame2.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new NewJFrame2().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JTextField jTextField1;
private javax.swing.JTextField jTextField2;
private javax.swing.JTextField jTextField3;
private javax.swing.JTextField jTextField4;
private javax.swing.JTextField jTextField5;
// End of variables declaration
}

Acquiring file icon makes JPanels disappear?

So recently I've started learning some Java , I've had experience in other languages (mostly web oriented ones like PHP , HTML etc. ) . So I started with some small project to like simple launcher / desktop overlay. Based on JPanel and here it started to get problematic .
I wanted to achieve something like windows 7 task-bar with applications that I can pin onto. So I started to look around for way to look for "extracting" icon from exe file into Java. Found some topic on this site most of the answers is just URL to this site.
All of these work but the problem is , when I call for these functions (like getSystemIcon) it makes all panels above (parents ) disappear. I can get all of them back by repainting , but is there another solution to that or I'm just doing something wrong?
Code:
import java.awt.Color;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.Graphics;
import java.io.File;
import javax.swing.Icon;
import javax.swing.JPanel;
import javax.swing.filechooser.FileSystemView;
public class Startbar extends JPanel{
private static final long serialVersionUID = 1L;
Config cfg = new Config();
public Startbar() {
setPreferredSize(new Dimension(cfg.Resx,35));
setBounds(0,1015,cfg.Resx,35);
setVisible(true);
this.setLayout(null);
StartbarClock clock = new StartbarClock();
clock.setBounds(cfg.Resx-135,0, 135, 35);
this.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
add(clock);
AddPins();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.black);
g.fillRect(0, 0, cfg.Resx, 35);
repaint();
}
public void AddPins(){
String filename = "C:/Program Files (x86)/Skype/Phone/Skype.exe";
Icon ico = FileSystemView.getFileSystemView().getSystemIcon(new File(filename));
System.out.println(ico.getIconHeight());
}
}
EDIT :
After adding timeout of 1 sec to the function everything works as it should ... wtf ?
Some code :
public class Startbar extends JPanel{
ActionListener listener = new ActionListener(){
public void actionPerformed(ActionEvent event){
pin();
}
};
Timer timer = new Timer(1000 ,listener);
private static final long serialVersionUID = 1L;
Config cfg = new Config();
public Startbar() {
setPreferredSize(new Dimension(cfg.Resx,35));
setBounds(0,1015,cfg.Resx,35);
setVisible(true);
setBackground(Color.black);
this.setLayout(null);
StartbarClock clock = new StartbarClock();
add(clock);
timer.start();
//pin();
}
public void pin(){
String filename = "C:/Program Files (x86)/Skype/Phone/Skype.exe";
FileSystemView view = FileSystemView.getFileSystemView();
Icon icon = view.getSystemIcon(new File(filename));
System.out.println(icon.getIconHeight());
timer.stop();
}
}
For what you are trying to do, set StartBar's background to black, then you don't need to overwrite paintComponet.
Don't set StartBar's bounds, use set/getPreferredSize instead. This will allow the parent container the oppurtunity to calculate the best size for the component (which might explain your problem)
You seriously should conisder the use of layout managers.
I'd have two child panels (content & task). I'd place all the application icons in the content, probably with a flow layout & the clock as/in the task, again, probably using a flow layout. Then I'd use either a grid bag layout or a border layout to add them to the task bar panel.
It might not seem like it, but ts going to make your life so much easier in the long run
UPDATE
Okay, then please explain to me why mine works then:
And look, no need to override paintComponent or repaint in sight.
public class TaskBarPane extends javax.swing.JPanel {
/**
* Creates new form TaskBarPane
*/
public TaskBarPane() {
initComponents();
setPreferredSize(new Dimension(800, 24));
pinTask(new File("C:/Program Files/BabyCounter/BabyCounter x64.exe"));
}
protected void pinTask(File task) {
pnlContent.add(new TaskPane(task));
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
pnlContent = new javax.swing.JPanel();
pnlClock = new test.ClockPane();
setBackground(new java.awt.Color(0, 0, 0));
setLayout(new java.awt.BorderLayout());
pnlContent.setOpaque(false);
java.awt.FlowLayout flowLayout1 = new java.awt.FlowLayout(java.awt.FlowLayout.LEFT);
flowLayout1.setAlignOnBaseline(true);
pnlContent.setLayout(flowLayout1);
add(pnlContent, java.awt.BorderLayout.CENTER);
pnlClock.setOpaque(false);
add(pnlClock, java.awt.BorderLayout.EAST);
}// </editor-fold>
// Variables declaration - do not modify
private test.ClockPane pnlClock;
private javax.swing.JPanel pnlContent;
// End of variables declaration
}
..
public class ClockPane extends javax.swing.JPanel {
/**
* Creates new form ClockPane
*/
public ClockPane() {
initComponents();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
jLabel1 = new javax.swing.JLabel();
setLayout(new java.awt.GridBagLayout());
jLabel1.setForeground(new java.awt.Color(255, 255, 255));
jLabel1.setText("Hello World");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 100;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8);
add(jLabel1, gridBagConstraints);
}// </editor-fold>
// Variables declaration - do not modify
private javax.swing.JLabel jLabel1;
// End of variables declaration
}
..
public class TaskPane extends javax.swing.JPanel {
/**
* Creates new form TaskPane
*/
public TaskPane() {
initComponents();
}
public TaskPane(File task) {
this();
Icon ico = FileSystemView.getFileSystemView().getSystemIcon(task);
lblIcon.setIcon(ico);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
lblIcon = new javax.swing.JLabel();
setOpaque(false);
setLayout(new java.awt.GridBagLayout());
lblIcon.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
lblIcon.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
lblIcon.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
add(lblIcon, new java.awt.GridBagConstraints());
}// </editor-fold>
// Variables declaration - do not modify
private javax.swing.JLabel lblIcon;
// End of variables declaration
}
...
public class TestFrame extends javax.swing.JFrame {
/**
* Creates new form TestFrame
*/
public TestFrame() {
initComponents();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
pnlTaskBar = new test.TaskBarPane();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
getContentPane().add(pnlTaskBar, java.awt.BorderLayout.CENTER);
pack();
}// </editor-fold>
/**
* #param args the command line arguments
*/
public static void main(String args[]) {
/*
* Set the Nimbus look and feel
*/
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/*
* If Nimbus (introduced in Java SE 6) is not available, stay with the
* default look and feel. For details see
* http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(TestFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(TestFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(TestFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(TestFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/*
* Create and display the form
*/
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new TestFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private test.TaskBarPane pnlTaskBar;
// End of variables declaration
}
It took me 10 mins to put together (had to feed my 11 week old daughter, sorry)
I added System.out.println("inRepaint") into your paintComponent method and ran the code...
16
inRepaint
inRepaint
inRepaint
inRepaint
inRepaint
inRepaint
inRepaint
inRepaint
inRepaint
inRepaint
inRepaint
inRepaint
inRepaint
inRepaint
...
My CPU usage ramped up to 85% before I killed it.
When I took it out, I got 4-5 as I resized the window with a cpu of around 7% before it went back to 1%
So, yeah, your code broke.

Using CardLayout in Java

I'm currently trying to make a game with a menu.
Menu looks like this.
http://puu.sh/xGoC
Ideally, when I push a button, it will bring me to the game.
The game looks like this.
http://puu.sh/xGoV
I currently initialize a JFrame() in my main class which runs either the menu class or the game class (Both of which are JPanels).
How would I go about using CardLayout to make it so that I can initialize the game menu and when I click a button, change the panel to the game panel?
I've got some sample code for you, it's not perfect, but it should work. Basically, you want to use the NEXT or PREVIOUS calls on the layout manager.
As there's only two panels, I just use the NEXT call to cycle through them. It's probably the best if you read the Swing documentation though, this works, but you might have other requirements as well.
import java.awt.CardLayout;
public class CardLayoutUsage extends javax.swing.JFrame {
public CardLayoutUsage() {
initComponents();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
containerPanel = new javax.swing.JPanel();
menuPanel = new javax.swing.JPanel();
jButton2 = new javax.swing.JButton();
gamePanel = new javax.swing.JPanel();
jButton1 = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
containerPanel.setLayout(new java.awt.CardLayout());
menuPanel.setBackground(new java.awt.Color(153, 255, 255));
jButton2.setText("Go to Game");
jButton2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton2ActionPerformed(evt);
}
});
javax.swing.GroupLayout menuPanelLayout = new javax.swing.GroupLayout(menuPanel);
menuPanel.setLayout(menuPanelLayout);
menuPanelLayout.setHorizontalGroup(
menuPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, menuPanelLayout.createSequentialGroup()
.addContainerGap(135, Short.MAX_VALUE)
.addComponent(jButton2)
.addGap(149, 149, 149))
);
menuPanelLayout.setVerticalGroup(
menuPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, menuPanelLayout.createSequentialGroup()
.addContainerGap(141, Short.MAX_VALUE)
.addComponent(jButton2)
.addGap(134, 134, 134))
);
containerPanel.add(menuPanel, "card2");
gamePanel.setBackground(new java.awt.Color(255, 255, 204));
jButton1.setText("Go to Menu");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
javax.swing.GroupLayout gamePanelLayout = new javax.swing.GroupLayout(gamePanel);
gamePanel.setLayout(gamePanelLayout);
gamePanelLayout.setHorizontalGroup(
gamePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, gamePanelLayout.createSequentialGroup()
.addContainerGap(138, Short.MAX_VALUE)
.addComponent(jButton1)
.addGap(147, 147, 147))
);
gamePanelLayout.setVerticalGroup(
gamePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, gamePanelLayout.createSequentialGroup()
.addContainerGap(152, Short.MAX_VALUE)
.addComponent(jButton1)
.addGap(123, 123, 123))
);
containerPanel.add(gamePanel, "card3");
getContentPane().add(containerPanel, java.awt.BorderLayout.CENTER);
pack();
}// </editor-fold>
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
CardLayout cl = (CardLayout)(containerPanel.getLayout());
cl.next(containerPanel);
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
CardLayout cl = (CardLayout)(containerPanel.getLayout());
cl.next(containerPanel);
}
/**
* #param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(CardLayoutUsage.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(CardLayoutUsage.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(CardLayoutUsage.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(CardLayoutUsage.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new CardLayoutUsage().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JPanel containerPanel;
private javax.swing.JPanel gamePanel;
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JPanel menuPanel;
// End of variables declaration
}
Don't use CardLayout for that.
Instead, remove the menu panel from the frame's content pane and add the game panel.
Remember to validate() the frame as well. Something like this:
public static final int VIEW_MENU = 0;
public static final int VIEW_GAME = 1;
private static Container content;
...
content = frame.getContentPane();
public static void setView(int view){
if(view == VIEW_MENU){
content.remove(menuPanel);
content.add(gamePanel);
} else {
content.remove(gamePanel);
content.add(menuPanel);
}
frame.validate();
}
In the program that I'm currently working on I have a class called ViewManager that creates static instances of each view and adds them to an array with indices that correspond to the constant fields. I also have fields to keep track of previous views for breadcrumbs / going back. It might be a case of re-inventing the wheel, but it allows you to control everything about it. And it's efficient.

JPanel Not displaying Buttons

I am trying to get a JPanel to display a series of Buttons.On each of these buttons is one of the values associated to my Sudoku Board Values. I have created my board added a menu and now i am trying to display the selectable options below the menu but before the board..in the same Jframe. I was hoping i could put all my buttons onto the JPanel and put that panel onto the Frame. It will display the JPanel but none of the buttons. At one time i got the panels to display but none of them were sized and there were to many. The question i have to be more specific is the code i am using correct for displaying my series of buttons on my JPanel, that is placed on in a Frame containing my Sudoku Board, which is also a series of buttons.
Is this final toolbar and buttons to much for this single JFrame, is that why it is not working? Anyways here is just the code for my toolbar which is my JPanel.
class ToolBar extends JPanel {
// instance initializer (constructor equivalent)
public ToolBar() {
super();
this.setLayout(myLayout);
myLayout.setAlignment(FlowLayout.TRAILING);
Button[] panelButton = new Button[size];
//Rectangle rec = new Rectangle(330,45,BUTTON, BUTTON);
//setBounds(rec);
setPreferredSize(new Dimension(330, 45));
for(int i = 0; i < size; i++) {
Rectangle r = new Rectangle(12, 12, 22, 22);
center = new ImageIcon(view.drawSymbol(i));
panelButton[i]= new Button();
panelButton[i].setIcon(center);
panelButton[i].setOpaque(true);
panelButton[i].setBorder(BorderFactory.createLineBorder(Color.black));
panelButton[i].setBounds(r);
this.add(panelButton[i]);
this.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
this.setVisible(true);
}
}
};
I used setBounds on the toolbar to make it visible and also set the background to red just for testing it, replaced AWT buttons with Swing JButtons and I also set some text on the buttons. I commented out something on my testing code in order to compile and but put them back below:
class ToolBar extends JPanel {
// instance initializer (constructor equivalent)
public ToolBar() {
super();
this.setLayout(myLayout);
myLayout.setAlignment(FlowLayout.TRAILING);
JButton[] panelButton = new JButton[5];
this.setBackground(Color.red);
this.setBounds(0, 0, 200, 200);
//Rectangle rec = new Rectangle(330,45,BUTTON, BUTTON);
//setBounds(rec);
setPreferredSize(new Dimension(330, 45));
for (int i = 0; i < 5; i++) {
Rectangle r = new Rectangle(22, 22);
panelButton[i] = new JButton();
panelButton[i].setText(" ");
panelButton[i].setIcon(new ImageIcon(view.drawSymbol(i)));
panelButton[i].setOpaque(true);
panelButton[i].setBorder(BorderFactory.createLineBorder(Color.black));
panelButton[i].setBounds(r);
this.add(panelButton[i]);
this.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
this.setVisible(true);
}
}
};
I am also posting the whole testing code below:
import java.awt.Color;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.Rectangle;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
/*
* To change this template, choose Tools | Templates and open the template in
* the editor.
*/
/**
*
* #author hahahaha
*/
public class NewJFrame extends javax.swing.JFrame {
/**
* Creates new form NewJFrame
*/
public NewJFrame() {
initComponents();
this.add(new ToolBar());
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE)
);
pack();
}// </editor-fold>
/**
* #param args the command line arguments
*/
public static void main(String args[]) {
/*
* Set the Nimbus look and feel
*/
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/*
* If Nimbus (introduced in Java SE 6) is not available, stay with the
* default look and feel. For details see
* http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/*
* Create and display the form
*/
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new NewJFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
// End of variables declaration
class ToolBar extends JPanel {
// instance initializer (constructor equivalent)
public ToolBar() {
super();
//this.setLayout(myLayout);
//myLayout.setAlignment(FlowLayout.TRAILING);
JButton[] panelButton = new JButton[5];
this.setBackground(Color.red);
this.setBounds(0, 0, 200, 200);
//Rectangle rec = new Rectangle(330,45,BUTTON, BUTTON);
//setBounds(rec);
setPreferredSize(new Dimension(330, 45));
for (int i = 0; i < 5; i++) {
Rectangle r = new Rectangle(22, 22);
//center = new ImageIcon(view.drawSymbol(i));
panelButton[i] = new JButton();
panelButton[i].setText(" ");
//panelButton[i].setIcon(center);
panelButton[i].setOpaque(true);
panelButton[i].setBorder(BorderFactory.createLineBorder(Color.black));
panelButton[i].setBounds(r);
this.add(panelButton[i]);
this.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
this.setVisible(true);
}
}
};
}
Look for the line this.add(new ToolBar()); where I instantiate and add your toolbar to my JFrame.
A piece of advice:
Avoid AWT components as much as possible
Don't use setPreferredSize or setBounds; let the LayoutManager handle the position and dimensions for you.
Depending on your needs, you may want to consider using a JToolBar instead of implementing your own.

Categories