So I am working with JComboBox in my new program, but for some reason every time something is selected it repaints. I do not want it to repaint the entire program when something is selected, just the boxes specified. See the code below.
The first section here is from the class that contains the panel.
First here are the declarations for the JComboBox's and the Labels they edit once selected:
private JComboBox crewview = new JComboBox(SpaceGame.stuffselector);
private JComboBox resourceview = new JComboBox(SpaceGame.stuffselector1);
private JLabel crewmember, crewmember1, crewmember2;
private JLabel resourcev, resourcev1, resourcev2;
where stuff selector is an array of number digits 1 to 10
My paint method containts these, as it does not work unless I have these here:
resourceview.setLocation(400,80);
resourcev.setLocation(455,85);
resourcev1.setLocation(455,95);
resourcev2.setLocation(455,105);
crewview.setLocation(400, 20);
crewmember.setLocation(455,25);
crewmember1.setLocation(455,35);
crewmember2.setLocation(455,45);
And here are my action listeners:
private class crewviewListener implements ActionListener{
public void actionPerformed(ActionEvent e){
lifeForm temp = SpaceGame.playership.getCrewat(crewview.getSelectedIndex());
crewmember.setText("Name: " + temp.getName()); //set the text to the crew member
crewmember1.setText("Race: " + temp.getRace());
crewmember2.setText("Worth: " + temp.getWorth());
}
}
private class resourceviewListener implements ActionListener{
public void actionPerformed(ActionEvent e1){
Resource temp1 = SpaceGame.playership.getResourceat(resourceview.getSelectedIndex());
resourcev.setText("Name: " + temp1.getName()); //set the text to the crew member
resourcev1.setText("Worth: " + temp1.getWorth());
resourcev2.setText("Amount: " + temp1.getAmount());
}
}
So as you may tell be reading the code, I am trying to get it to only update the JLables when stuff in the box is selected, and not repaint everything.
JLabels are non-opaque by default. This means that whenever you change the text in the label, the background of the label must also be repainted. Therefore the panel that contains the label will also be repainted.
Swing will usually determine a clipped area of the panel to be repainted. That is the rectangular area that contains the 3 labels will be repainted, not the entire panel.
Post a SSCCE that demonstrates the problem if you need more help.
Related
*This is my first time using GUI, I seem to miss something my eye can't catch. The code looks fine to me however when i submit it to autoLab I get this error, which I cannot figure out where I went wrong.
{"correct":false,"feedback":"(class java.lang.NumberFormatException)
Error while attempting to call static method q2() on input [1]}
The problem question is q5:
Write a public static method named q5 that takes no parameters and returns a JPanel.
The panel will contain 1 JTextField with any number of columns, 1 JButton with any label,
and 1 JLabel. The panel will have functionality such that when a user enters a number into
the text field (we'll call this value x) and presses the button the label will display the
y-value of a parabola in standard form (https://www.desmos.com/calculator/zukjgk9iry)
where a=5.37, b=-6.07, and c=2.0 at the x-value from the text field
Hint: If you store y in the wrapper class Double instead of the primitive double you can
call toString on it to convert it to a string that can be used as the text for the label
Tip: After clicking the button you may have to resize your window to see the result since
the frame will not automatically resize to fit the new text
Do not create any JFrames in your problem set questions. Doing so will crash the
auto-grader since the grading server does not have a screen to display the JFrame.
Instead, only return the required JPanel in the problem set methods and test with a JFrame
in your main method, or other helper methods that are not graded
This is the code I wrote
public static JPanel q5() {
JPanel panel = new JPanel();
JTextField textField = new JTextField(5);
panel.add(textField);
JLabel label = new JLabel("hello!");
panel.add(label);
JButton button = new JButton("Click Me!");
panel.add(button);
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
int x = Integer.parseInt(textField.getText());
double a=5.37*Math.pow(x, 2);
double b=-6.07*x;
double c=2.0;
String answer= ("y = " + a+ b +c);
label.setText(answer);
}
});
return panel;
}
can you explain where I went wrong , thank you.
So, a NumberFormatException can occur when trying to parse a String, when the String does not contain a number. You did not give enough information to be sure, but I am going to presume that it is this line that causes the problem:
int x = Integer.parseInt(textField.getText());
One thing that strikes me as odd, is that you initialize the JTextField with 5 columns:
JTextField textField = new JTextField(5);
Is that what you want? If you wanted to pre-initialize the text field with a value of 5, you would have to do it like this:
JTextField textField = new JTextField("5");
I have a display that just shows a score on a page:
for example:
JIMBOB
Total Score: 22
When a point is scored an event is triggered that updates the score and redraws the new score on the page:
public void showScore(String username, int score)
{
contentPane.remove(layout.getLayoutComponent(BorderLayout.CENTER));
score.setText("<html>" + username + "<br/>Total Hits: " + totalHits + "</html>");
contentPane.add(score, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
Every time a point is scored this function is called, it removes the old score message adds an new one then packs and redraws.
The problem is that the window flickers when drawing the updated frame. And it seems for a split second to be displaying the info unformatted
contentPane is a Container
and frame is a JFrame
Invoking pack() will completely re-render the JFrame, a top-level, heavyweight container owned by the host platform. Instead, update the JComponent used to display the revised score. A complete example is cited here. Excerpted form RCStatus,
public class RCStatus extends JPanel implements Observer {
/** Update the game's status display. */
public void update(Observable model, Object arg) {
// invoke setText() here
}
}
See this answer for more on the observer pattern.
First of all, I would recommend to take a look at how to use JPanels and other GUI components in Swing. You could use a JPanel to be added to the contentPane of your JFrame. Add a desired LayoutManager that is fitting for your need and use it to position a JLabel according to your wishes.
When you call your showScore() method, use setText(String text) on a JLabel instead of the int score that you supply as parameter.
In order to set the text using a String, you need to transform your int score. You can do either of the following two things (but use the first option):
label.setText(String.valueOf(score));
label.setText("" + score);
If you want the score label to appear or disappear, add/ remove it from the JPanel that you added to the JFrame. After adding it, call setText() on the label to display the score. Then, since you reset the text of the label, you should call repaint() on the JPanel. If you choose to add/ remove the JLabel instead of just changing its text you should also call revalidate() on the JPanel.
So all in all the function should look something like this (this is incomplete), assuming totalHits is actually your score.
// declare instance fields before constructor
// both variables are reachable by showScore()
private JPanel scorePanel;
private JLabel scoreLabel;
// in constructor of your class
scorePanel = new JPanel(); // initialize the JPanel
scorePanel.setLayout(new BorderLayout()); // give it a layout
scoreLabel = new JLabel(); // initialize the label
frame.add(scorePanel); // add JPanel to your JFrame
// method obviously outside constructor
public void showScore(String username, int score)
{
// clear the JPanel that contains the JLabel to remove it
scorePanel.removeAll();
scoreLabel.setText("<html>" + username + "<br/>Total Hits: " + String.valueOf(score) + "</html>");
scorePanel.add(label, BorderLayout.CENTER);
scorePanel.revalidate();
scorePanel.repaint();
}
You could also declare and initialize the JPanel and JLabel in the showScore() method, making it more local. But then you would also need to call pack() on the JFrame and clear the previous JPanel from it every time you call the function.
.
I created a frame. within the frame there is a combobox.
I am trying that each option from the combobox will create something else (JCheckBox,JRadioButton).
comboBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
String selection = comboBox.getSelectedItem().toString();
label3.setText(input[comboBox.getSelectedIndex()]);
//panel_mid.removeAll();
if(comboBox.getSelectedItem().toString().equals("Pilot")){
panel_mid.removeAll();
panel_mid.add(label3,BorderLayout.WEST);
panel_mid.add(text_bottom);
panel_mid.setBorder(new TitledBorder(comboBox.getSelectedItem().toString() + " options"));
panel_mid.add(jchkCaptain);
}
if(comboBox.getSelectedItem().toString().equals("Host")){
panel_mid.removeAll();
panel_mid.add(label3,BorderLayout.WEST);
panel_mid.add(text_bottom);
panel_mid.setBorder(new TitledBorder(comboBox.getSelectedItem().toString() + " options"));
panel_mid.add(regular = new JRadioButton("Regular"));
panel_mid.add(bachir = new JRadioButton("Bachir"));
panel_mid.add(calcelan = new JRadioButton("Calcelan"));
}
if(comboBox.getSelectedItem().toString().equals("Office")){
panel_mid.removeAll();
panel_mid.add(label3,BorderLayout.WEST);
panel_mid.add(text_bottom);
panel_mid.setBorder(new TitledBorder(comboBox.getSelectedItem().toString() + " options"));
}
}
});
when picked Pilot only JCheckBox shuold appear.
when picked Host only JRadioButton shuold appear.
when picked Office nothing shuold appear.
the problem is when i pick host and then pilot and then host it doesnt show the JRadioButton.
thanks for help.
you have to tell the LayoutManager something is/are changed, LayoutManager haven't any notifier about, you have to notify programatically about this changes
use container.revalidate() and container.repaint(variable for JPanels in your case) as last code line, only one time ,after all changes to the already visible Swing GUI are done
use CardLayout for to switch between views (JPanels in your case)
I would like to customize JTableHeader so it would offer serval actions (for example 2 buttons which one of them would sort column and second show properties of this column etc). Unfortunately it is not possible to set CellEditor for JTableHeader so i'm stuck with using mouse adapter. But maybe it is possible to dispatch event from this particular JTableHeader component so it will show up a popup menu which will contains all options i desire and it would dispatch event if option other than sorting would be chosen. This way standard JTable sorting operation will be available, along with my operations and it will maintain a decent visual apperance. So my question is - Is it possible and how it should be done.
In response to trashgod comment - i understand that you mean to treat defaultheader as an ordinary component and just use "add" function to add Components. It doesnt work well with JTableHeader. After reading trashgod example i wrote this:
private class mouseList extends MouseAdapter {
#Override
public void mouseClicked(MouseEvent e) {
TableColumnModel thisColumnModel = thisTable.getColumnModel();
int xCor = e.getX();
//int Cols = thisColumnModel.getColumnCount();
int thisColNum = thisColumnModel.getColumnIndexAtX(xCor);
int prevWidth=0;
for(int i = 0 ;i<thisColNum;i++)
{
prevWidth+=thisColumnModel.getColumn(i).getWidth();
}
int width = xCor-prevWidth;
/////////////////////////////////////////////////////////////////////////////////////
customHeader thisHeader = (customHeader)((JTableHeader)e.getSource()).getDefaultRenderer();
System.out.println(thisHeader.mainB.getText() + " text of thisHeader");
//////////////////////////////////////////////////
test thisTest = new test(null,false,thisHeader);
thisTest.setVisible(true);
///////////////////////////////////////////////////////////////
//System.out.println(width + " width of the header");
Object thisComp = thisHeader.getComponentAt(width, e.getY());
System.out.println(thisComp + "\n" + width + " + " + e.getY() +"\n" + thisHeader.getMainButton().getText());
((JTableHeader)e.getSource()).repaint();
if(thisComp instanceof JButton)
{
//System.out.println("sdfdsf");
String name = ((JButton)thisComp).getName();
if(name.equals("mainB"))
{
System.out.println("its working on main");
((JButton)thisComp).doClick(1000);
}else{
System.out.println("its working on menu");
((JButton)thisComp).doClick(1000);
}
}
((JTableHeader)e.getSource()).repaint();
}
}
MouseListener is applied to JTableHeader. HeaderRender is an extension of JPanel that contains 2 JButtons. Strange thing happens in line
Object thisComp = thisHeader.getComponentAt(width, e.getY());
When i left lines
test thisTest = new test(null,false,thisHeader);
thisTest.setVisible(true);
(This dialog shows selected component)
uncommented, function "getComponentAt" seems to work allmost fine (allmost because it never goes for else condition even when mouse is targeting second button, and it does not repaint clicked buttons[Strangely its repainting buttons in test dialog window]),otherwise it allways returns null object.
I dont know if it is important but i set Header renderer globally by invoking "setDefaultRenderer" on JTableHeader.
Im pretty much running out of ideas so i would appreciate any help.
This example shows the basic infrastructure, while this answer offers several important caveats regarding usability. This example shows how to change the RowFilter dynamically, but changing the RowSorter is similar. Both examples use JToggleButton to manage two states, but a JComboBox could be used to select from among more alternatives.
I am creating a class that acts as a container which holds a label and buttons. I want the buttons to only appear when I mouseover the label on a new layer, and be clickable, but this is not my question (I have discovered OyverLay Layout and JLayeredPane for this purpose, and I will figure that out later). Like I said I plan to use JLayeredPane vs regular JPanel (because of it's multi layer abilities) most likely, but my first question is this the correct type of container to use if this class will instantiate objects onto another classes JFrame container? I don't think it is because as a panel it creates a window with a title bar and buttons, and I don't want that. I just want this class to instantiate a box with my label and buttons and add it to a JFrame to be in a grid with other buttons???
My main issue is, I want this container that holds the label and buttons to be added to a JFrame that is apart of a class who's main job is to hold the containers from my first class and have the user be able to add more and remove via a UI.
Essentially I want a form with text boxes and a button, and the button adds a new ListItem object to the JFrame of another class and the new objects label text is built form the text boxes, instantiating a new object on that JFrame. So, if I hit the button 5 times I'll see 5 boxes with 5 labels in them with unique words one right on top of the other.
I have looked into using the root container, using JInternalFrames, and tried every other magic tricks but can't seem to get it to work right.
Here is the code for the class I have built.
*above this in my class is the importing of the objects I need, and the creation of various strings, buttons and labels used here. what I have pasted here is the meat of my code, the object which is created and displayed when instanciated***
public ListItem(String nameC, String timeC, String recordNum)
{
JLayeredPane panel1 = new JLayeredPane();
name = nameC; time = timeC; recordN = recordNum;
//fullItemString is a String object
fullItemString = "Help " + name + " at " + time + " regarding " + "Record # " + recordNum;
//item is a label
item.setText(fullItemString);
item.setFont(verdana);
minusButton.putClientProperty("JButton.buttonType", "square");
exportButton.putClientProperty("JButton.buttonType", "square");
editButton.putClientProperty("JButton.buttonType", "square");
// setSize(425, 50);
//setDefaultCloseOperation(EXIT_ON_CLOSE);
minusButton.setBounds(175, -1, 35, 30);
editButton.setBounds(210, -1, 35, 30);
exportButton.setBounds(130, -1, 35, 30);
panel1.add(minusButton);//, new Integer(2));
panel1.add(top);//, new Integer(1));
panel1.add(editButton);//, new Integer(3));
panel1.add(exportButton, new Integer(4));
minusButton.addActionListener(this);
item.addMouseListener(this);
exportButton.setVisible(false);
minusButton.setVisible(false);
editButton.setVisible(false);
lp.setVisible(true);
setVisible(true);
}
Multiple panel adding in JFrame using CardLayout. try it...