I have got few comboBoxes like:
final JComboBox listCosN = new JComboBox();
listCosN.setBounds(289, 261, 36, 20);
painting.add(listaCosN);
listCosN.addItem(1);
listCosN.addItem(2);
listCosN.addItem(3);
listCosN.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
int choosedCosN = listCosN.getSelectedIndex();
}
});
And now i want to use those choosed items from all of the comboBoxes. Doing simply
(for ex.)
int x = choosedCosN; after "});"
doesn't solve anything, because "int x cannot be resolved to a variable". That means choosed items are like local variables? How can i solve this?
Related
This question already has answers here:
Variable cannot be resolved
(6 answers)
Closed 5 years ago.
I am creating a JList like so:
JScrollPane scrollPane = new JScrollPane();
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
GridBagConstraints gbc_scrollPane = new GridBagConstraints();
gbc_scrollPane.insets = new Insets(0, 0, 5, 5);
gbc_scrollPane.fill = GridBagConstraints.BOTH;
gbc_scrollPane.gridx = 0;
gbc_scrollPane.gridy = 1;
contentPanel.add(scrollPane, gbc_scrollPane);
{
JList listAvail = new JList();
listAvail.setBorder(new TitledBorder(null, "", TitledBorder.LEADING, TitledBorder.TOP, null, null));
scrollPane.setViewportView(listAvail);
}
and I'm trying to access it when a button is clicked:
JButton btnAdd = new JButton("Add ->");
btnAdd.addMouseListener(new MouseAdapter()
{
#Override
public void mouseClicked(MouseEvent arg0)
{
if (!listAvail.isSelectionEmpty())
{
int[] selects = listAvail.getSelectedIndices();
for (int i = selects.length - 1; i >= 0; i--)
{
appliedM.add(0, availM.getElementAt(selects[i]));
appliedFeatures.add(0, availFeatures.get(selects[i]));
availFeatures.remove(availFeatures.get(selects[i]));
availM.remove(selects[i]);
}
}
}
});
Of course, I'm getting an error saying "listAvail cannot be resolved" since it's out of the button's scope. Is there a getter method or a way to drill down to a specific component? I'm thinking something along the lines of:
contentPanel.scrollPane.listAvail
There must be something I'm missing but I haven't seen anything like this in the docs.
Edit: I am asking specifically about drilling down to a swing component. This is not a generic variable scoping question and not an exact duplicate of the referenced question. This question has yet to be answered at the time of this edit.
Your question boils down to -- how do I access an object reference when it is assigned to a very locally scoped variable, here the object being the JList, and the variable it's being assigned to is listAvail, a variable buried within its own set of curly braces (why?) within a method or constructor.
The solution -- get the variable declaration out of the local scope and make it instead an instance field of the class. e.g.,
public class MyClass {
private JList listAvail = new JList(); // should be generic btw
Another issue is here:
btnAdd.addMouseListener(new MouseAdapter() {....
Don't use a MouseListener with a JButton where an ActionListener is much more appropriate. This has ramifications if you want the button's actions to be disabled when the button itself is disabled.
I created a class that can dynamically to lock and unlock columns .
In my program i create two tables with the same tablemodel.
One is in the Jviewport of the scrollpane, the other in the RowHeaderView.
The problem is when you unlock all the locked columns
and you want to start to lock again, doesn't work. There are no errors but it's like the event doesn't answer.
Steps to produce the problem:
Try the code,
put all the columns in the fixed table,
then unlock with right double click,
then start again to lock, and unlock
Do this procedure and you can see that the mouse event doesnt answer anymore
public class Prova extends JFrame{
private JTable mainTable,fixedTable;
private JScrollPane scrollPane;
private JTableHeader mainTableHeader;
private TableColumnModel originalColumnModel,mainColumnModel,fixedColumnModel;
private TableColumn[] columns;
private int ncols,counter;
public Prova(){
counter = 0;
TableModel mainTableModel = new DefaultTableModel(5, 10);
scrollPane = new JScrollPane();
mainTable = new JTable(mainTableModel);
mainColumnModel = mainTable.getColumnModel();
fixedTable = new JTable();
fixedTable.setAutoCreateColumnsFromModel(false);
fixedTable.setModel(mainTable.getModel() );
ncols = mainTableModel.getColumnCount();
columns = new TableColumn[ncols];
for (int i=0;i<ncols;i++){
columns[i] = mainColumnModel.getColumn(i);
}
mainColumnModel = mainTable.getColumnModel();
fixedColumnModel = fixedTable.getColumnModel();
mainTableHeader = mainTable.getTableHeader();
mainTableHeader.addMouseListener( new MouseAdapter(){
#Override
public void mouseClicked(MouseEvent me){
if (SwingUtilities.isRightMouseButton(me)){
if (ncols - counter>1){
counter ++;
int col = mainTable.columnAtPoint(me.getPoint());
TableColumn column = mainColumnModel.getColumn(col);
mainColumnModel.removeColumn(column);
fixedTable.getColumnModel().addColumn(column);
scrollPane.setRowHeaderView(fixedTable);
scrollPane.setCorner(JScrollPane.UPPER_LEFT_CORNER, fixedTable.getTableHeader());
}
}
}
});
fixedTable.getTableHeader().addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent me){
if (SwingUtilities.isRightMouseButton(me) && me.getClickCount()== 2 ){
while (mainColumnModel.getColumnCount() > 0){
mainColumnModel.removeColumn(mainColumnModel.getColumn(0));
}
while (fixedColumnModel.getColumnCount() > 0){
fixedColumnModel.removeColumn(fixedColumnModel.getColumn(0));
}
for(int i=0;i<ncols;i++){
mainColumnModel.addColumn(columns[i]);
}
scrollPane.setRowHeaderView(null);
}
}
});
scrollPane.setViewportView(mainTable);
add(scrollPane, BorderLayout.CENTER);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Prova().setVisible(true);
}
});
}
}
A few pointers when posting a SSCCE:
for (int i=0;i<ncols;i++){
Don't be afraid to use whitespace in you code to make it more readable be separating the 3 statements of the for statement.
for (int i = 0; i < ncols; i++){
Keep the code simple and directly related to the problem:
TableModel mainTableModel = new EmployeeTableModel(listEmployees);
You question is about "moving columns", not about the data in the table so there is no need for a special TableModel and the Employee class. Just use the DefaultTableModel:
TableModel mainTableModel = new DefaultTableModel(5, 10);
Your current code won't compile because you didn't include the Employee class. By using JDK classes the code is smaller and easier to read.
The problem is when you unlock all the locked columns and you want to start to lock again, doesnt work
Your looping code is wrong. I didn't bother to figure out what was wrong. Instead I made the code simpler:
//for(int i=0;i<(ncols-counter);i++){
while (mainColumnModel.getColumnCount() > 0)
{
mainColumnModel.removeColumn(mainColumnModel.getColumn(0));
}
//for(int i=0;i<counter;i++){
while (fixedColumnModel.getColumnCount() > 0)
{
fixedColumnModel.removeColumn(fixedColumnModel.getColumn(0));
}
Another problem is your fixed table doesn't have a header so you don't know what the columns are. This is fixed by using:
scrollPane.setRowHeaderView(fixedTable);
scrollPane.setCorner(JScrollPane.UPPER_LEFT_CORNER, fixedTable.getTableHeader());
Now that you have a header you need to add the MouseListener to the header, not the scrollpane:
//scrollPane.addMouseListener(new MouseAdapter() {
fixedTable.getTableHeader().addMouseListener(new MouseAdapter() {
Edit:
You have a similar problem to what I fixed above. That is don't keep using variable to track values when you can use the component itself.
if (ncols - counter>1){
You never reset the value of the counter so the if condition won't be true the second time.
As I did above just use the value from the column model:
//if (ncols - counter>1){
if (mainColumnModel.getColumnCount() > 1) {
This is just basic problem solving. Put a display statement in the block of code to see if it executes when you have problems.
Scenario: I have a series of jbuttons (created at runtime) and each of them has a number in his label. Buttons are created with this code:
for (int i = 1; i <= tablesNumber; i++) {
JButton button = new JButton(Integer.toString(i));
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new Orders().setVisible(true);
}
});
jPanel1.add(button);
}
I need to pass to the class Orders the number of the button which fires the event, e.g. if the user clicks on button number 5 I need to pass the value 5 to Orders.
How can I do this?
Thanks.
From your question:
pass to the class Orders the number of the button which fires the event
You could just capture the loop iteration variable i so it can be used inside your anonymous event handler. For the sake of argument I have assumed you want to pass the number into the constructor, but you can use it however you like:
for (int i = 1; i <= tablesNumber; i++) {
final int t = i; // <-- NEW LINE HERE
JButton button = new JButton(Integer.toString(i));
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new Orders(t).setVisible(true); // <-- USE t here however you need to
}
});
jPanel1.add(button);
}
Without final int t = i you may get the compiler error "Cannot refer to a non-final variable i inside an inner class defined in a different method". This is because a capture variable (i.e. a variable from an outer scope used inside an anonymous class' method must be final (or effectively final - this behaviour has changed slightly as of SE 8).
My goal is to delete two JTextFields at the same time by clicking a JLabel.
I've created the textfields like this:
public void mouseClicked(MouseEvent e) {
inc++;
txtName= new JTextField();
txtNumber = new JTextField();
txtName.setName("txtName"+inc);
txtNumber.setName("txtNumber" + inc);
pnlPanel.add(txtName);
pnlPanel.add(txtNumber);
if(count>0){
x+=50;
y+=50;
txtName.setBounds(225,6+y, 182, 27);
txtNumber.setBounds(35, 6+y, 182, 27);
txtName.setName(tempBox+count);
if(pnlTxtText.getComponentCount() >9){
pnlPanel.setPreferredSize(new Dimension(450+y,50+y));
pnlPanel.add(txtStudName);
pnlPanel.add(txtStudentNumber);
frmFrame.repaint();
scrpPanel.revalidate();
}
}
frmFrame.repaint();
}
});
And this is my code for removing the textfields:
public void mouseClicked(MouseEvent e) {
int countPlace= pnlPanel.getComponentCount();
int countOfRemaining =countPlace;
pnlPanel.remove(--countOfRemaining);
frmFrame.revalidate();
pnlPanel.remove(--countOfRemaining);
frmFrame.revalidate();
}
});
Instead of deleting the txtfields on the same row, it deletes it one by one, i dont want that. Please help me. Thank you.
Call pnlPanel.revalidate() before repaint()
And don't use setBounds(). Define porper LayoutManager instead.
Instead of this,
public void mouseClicked(MouseEvent e) {
int countPlace= pnlPanel.getComponentCount();
int countOfRemaining =countPlace;
pnlPanel.remove(countOfRemaining-1);
frmFrame.repaint();
pnlPanel.remove(countOfRemaining-1);
frmFrame.repaint();
}
});
Use this
public void mouseClicked(MouseEvent e) {
int countPlace= pnlPanel.getComponentCount();
int countOfRemaining =countPlace;
pnlPanel.remove(--countOfRemaining);
frmFrame.revalidate();
pnlPanel.remove(--countOfRemaining);
frmFrame.revalidate();
}
});
The above one throws an ArrayIndeOutOfBounds Exception because the count remaining variable is not being decremented after you remove a component. Hence the index goes out of bound when you try to remove the second time.
I recommend that you add all of your JPanels to a Map (I use HashMap) in the form of <Integer, JPanel>. Name them all in order, and then just do Map.remove(Map.size() - 1) and Map.remove(Map.size() - 2).
You can also get the current set of Integers (the keys) by doing a Map.keySet();
Map<Integer, JPanel> temp = new HashMap<Integer, JPanel>();
temp.put(0, new JPanel());
temp.put(1, new JPanel());
temp.put(2, new JPanel());
temp.remove(temp.size() - 1);
Makes it much easier to maintain numerous sets of panels. In my applications I don't control them numerically, but with short names instead.
1) In the following method (actionListener) a user select a grade (e.g. A-F) from a JComboBox.
2) There are multiple JComboBoxes, and each selection made gets stored into a single String[] array.
PROBLEM:
Here is the dilemma, if a user goes back and changes a selection made from a random JComboBox the previous grade selection does not get replaced in the array, however the new selection made gets stored at the next array index.
How can I make the program replace the previous grade selection and not just add the new selection?
relevant variables:
int counter;
private JComboBox[] gradeField;
//grade.userGrades[] is array of grades taken from selected combo boxes
Action Listener anonymous class:
gradeField[counter].addActionListener(new ActionListener () {
#Override
public void actionPerformed(ActionEvent e) {
Object holder = e.getSource();
JComboBox tempGradeBox = (JComboBox)holder;
String theGrade = (String)tempGradeBox.getSelectedItem();
grade.userGrades[grade.getNext()] = theGrade;
grade.updateNext();
}
});
Thanks in advance for any help.
I save the grade in an array and increment the index,
Well you should not be incrementing the index. This assumes that the user selects the grades from the combo box in a sequential order. As you have discovered users can often work randomly.
Instead you need to know which combo box has been changed and then update the appropriate entry in your array.
Or a different solution might be to update your array at the end. So maybe you have a "Process Results" button. Then you can sequentually loop through all the combo boxes to get the selected value.
Update the user grade being at the same index as the combo box:
final int index = counter;
gradeField[counter].addActionListener(new ActionListener () {
#Override
public void actionPerformed(ActionEvent e) {
Object holder = e.getSource();
JComboBox tempGradeBox = (JComboBox)holder;
String theGrade = (String)tempGradeBox.getSelectedItem();
grade.userGrades[index] = theGrade;
}
});
Here's another variation of JB Nizet's answer:
class OuterClass
{
...
gradeField[counter].addActionListener( new GradeSettingActionListener( counter ) );
...
class GradeSettingActionListener implements ActionListener
{
// -- Doesn't have to be final here (it does in JB's answer), but I like to be restrictive.
private final int index;
public GradeSettingActionListener( int index )
{
this.index = index;
}
#Override
public void actionPerformed( ActionEvent e )
{
Object holder = e.getSource();
JComboBox tempGradeBox = (JComboBox) holder;
String theGrade = (String) tempGradeBox.getSelectedItem();
grade.userGrades[index] = theGrade;
}
}
}
This approach removes the anonymous class by adding an inner class. The inner class will still have access to grade. You don't gain much here unless there's a chance you'll be splitting out the inner class later.
Of course, camickr's suggestion to process all the grades at once may also be valid, depending on other requirements (i.e., whether additional processing is done after the grades are stored in the array, which seems likely).