1

I tried so far too much and was reading lots of things. Still couldn't find any working solution on my case. So, here is the deal. During the game, players money are changing. What I am trying to achieve is to display money instantly from the JTable, so the player can always follow his money by simply looking at the table. But, as you can assume, I failed at changing the money when it is changed. It just stays at the amount of how it started.

What I got so far is a well-built JTable which shows the initial money of player at beginning and a custom model for my JTable.

Since I believe the solution relies on the model and setValuesAt(Object value, int row, int column), I was trying to figure a way out there. What I got there is a method called refresh. To be more specific, let me show you some fraction of my code.

So here is my rowData array in the constructor, which I'm using for displaying the initial money at the beginning of the game:

rowData = new Object[][]{
                {GameFlow.getPlayer1().getName(), "Pink", GameFlow.getPlayer1().getMoney()},
                {GameFlow.getPlayer2().getName(), "Blue", GameFlow.getPlayer2().getMoney()},
                {GameFlow.getPlayer3().getName(), "Green", GameFlow.getPlayer3().getMoney()},
                {GameFlow.getPlayer4().getName(), "Red", GameFlow.getPlayer4().getMoney()},
        };

By saying that, I also need to show you these two following functions, setValueAt and refresh(refresh is a method I just wrote for simplicity for updating changes):

public void setValueAt(Object value, int row, int col) {
    rowData[row][col] = value;
    fireTableCellUpdated(row, col);
}
public void refresh(){
    for (int i = 0; i < 4; i++) {
        setValueAt(GameFlow.getPlayer1().getMoney(), i, 2);
    }
}

Here, in the refresh, I am only trying to change the second (2nd) row because the first two are static and never changes. Also, the number 4 in the for loop is the number of players, so that 4 holds the number of rows.

You can find at below the whole my table model code:

import javax.swing.table.AbstractTableModel;

public class MonopolyTableModel extends AbstractTableModel {
    private String[] columnNames = {
            "Name",
            "Color",
            "Money",
    };
    private Object[][] rowData;

    public MonopolyTableModel() {
        rowData = new Object[][]{
                {GameFlow.getPlayer1().getName(), "Pink", GameFlow.getPlayer1().getMoney()},
                {GameFlow.getPlayer2().getName(), "Blue", GameFlow.getPlayer2().getMoney()},
                {GameFlow.getPlayer3().getName(), "Green", GameFlow.getPlayer3().getMoney()},
                {GameFlow.getPlayer4().getName(), "Red", GameFlow.getPlayer4().getMoney()},
        };
    }
    @Override
    public int getRowCount() {
        return rowData.length; 
    }
    @Override
    public int getColumnCount() {
        return columnNames.length;
    }
    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        return rowData[rowIndex][columnIndex];
    }

    public void setValueAt(Object value, int row, int col) {
        rowData[row][col] = value;
        fireTableCellUpdated(row, col);
    }

    public String getColumnName(int columnIndex) {
        return columnNames[columnIndex];
    }

    public void refresh(){
        for (int i = 0; i < 4; i++) {
            setValueAt(GameFlow.getPlayer1().getMoney(), i, 2);
        }
    }

}

And that is how I use in the Gui class:

MonopolyTableModel monoModel = (MonopolyTableModel) dataTable.getModel();
monoModel.refresh();

Hope those are enough to show, if needed I can show more but since this is a school project I am avoiding to show much.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Kutay Demireren
  • 640
  • 1
  • 10
  • 25
  • Consider providing a [runnable example](https://stackoverflow.com/help/mcve) which demonstrates your problem. This is not a code dump, but an example of what you are doing which highlights the problem you are having. This will result in less confusion and better responses – MadProgrammer Oct 16 '15 at 00:42
  • Your `setValueAt` method has no relationship to the actual `player` object, so any values you change in the table won't effect the `player` object – MadProgrammer Oct 16 '15 at 00:43
  • Player's money is changing during the game, I am sure about it. So, setValueAt has nothing to do with changing the player. I just can't refresh on table. And sure, I will try to give more code for your convenience – Kutay Demireren Oct 16 '15 at 00:46

1 Answers1

2

It's a little hard to figure out what the problem might be based on the out-of-context code you have provided.

When ever I deal with a JTable, I use it to model the physical data, in your case, that's the Player object. This way, if the Player is modified outside of the table, you simply need to trigger a update to the model to have the table refresh the values. Equally, you can also centralise some of the functionality to the table and use it to modify the Player object directly.

This way, the model and the data are always in sync (even if the display isn't)

In this example, there are two ways to update the model/table.

First, you could update the Player object and ask the model to "refresh" the given player, for example...

Player player = model.getPlayerAt(selectedRow);
player.setMoney(player.getMoney() + 10);
model.update(player);

or you could have the model update the Player via the setValueAt method...

Player player = model.getPlayerAt(selectedRow);
model.setValueAt(player.getMoney() - 10, selectedRow, 1);

As a runnable example...

Updatable Table

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private PlayerTableModel model;

        public TestPane() {
            List<Player> players = new ArrayList<>(5);
            players.add(new Player("Han Solo", 100d));
            players.add(new Player("Dark Vadar", 100d));
            players.add(new Player("R2-D2", 100d));
            players.add(new Player("Darth Maul", 100d));
            players.add(new Player("Jawa", 100d));

            setLayout(new BorderLayout());
            model = new PlayerTableModel(players);
            JTable table = new JTable(model);
            add(new JScrollPane(table));

            JPanel actions = new JPanel();
            JButton add = new JButton("+");
            JButton subtract = new JButton("-");

            actions.add(add);
            actions.add(subtract);

            add.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    int selectedRow = table.getSelectedRow();
                    if (selectedRow >= 0) {
                        selectedRow = table.convertRowIndexToModel(selectedRow);
                        Player player = model.getPlayerAt(selectedRow);
                        player.setMoney(player.getMoney() + 10);
                        model.update(player);
                    }
                }
            });
            subtract.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    int selectedRow = table.getSelectedRow();
                    if (selectedRow >= 0) {
                        selectedRow = table.convertRowIndexToModel(selectedRow);
                        Player player = model.getPlayerAt(selectedRow);
                        model.setValueAt(player.getMoney() - 10, selectedRow, 1);
//                      player.setMoney(player.getMoney() - 10);
//                      model.update(player);
                    }
                }
            });

            add(actions, BorderLayout.SOUTH);

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.dispose();
        }

    }

    public static class PlayerTableModel extends AbstractTableModel {

        protected static final String COLUMNN_NAMES[] = {"Name", "Money"};

        private List<Player> players;

        public PlayerTableModel(List<Player> players) {
            this.players = new ArrayList(players);
        }

        public Player getPlayerAt(int row) {
            return players.get(row);
        }

        @Override
        public int getRowCount() {
            return players.size();
        }

        @Override
        public int getColumnCount() {
            return COLUMNN_NAMES.length;
        }

        @Override
        public String getColumnName(int column) {
            return COLUMNN_NAMES[column];
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            Player player = players.get(rowIndex);
            Object value = null;
            switch (columnIndex) {
                case 0:
                    value = player.getName();
                    break;
                case 1:
                    value = player.getMoney();
                    break;
            }
            return value;
        }

        @Override
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
            if (columnIndex == 1) {
                Player player = players.get(rowIndex);
                player.setMoney((double)aValue);
                super.setValueAt(aValue, rowIndex, columnIndex);
                fireTableCellUpdated(rowIndex, columnIndex);
            }
        }

        public void update(Player player) {
            int row = players.indexOf(player);
            fireTableRowsUpdated(row, row);
        }

    }

    public class Player {

        private String name;
        private double money;

        public Player(String name, double money) {
            this.name = name;
            this.money = money;
        }

        public double getMoney() {
            return money;
        }

        public String getName() {
            return name;
        }

        public void setMoney(double money) {
            this.money = money;
        }

    }

}

The point is, there shouldn't be such a disconnection between your players and your model, even if you need to wrap the player into another object so you can expand on the properties you want to display, at least this way, when you ask for a value, it's the same value that the object actually has and when you set it, it's been set on the same object.

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Although I tried, I think I wasn't clear enough about telling my problem, what you are telling me was not I was looking for. However, with your suggestion of association of players with the table, I re-read my whole code and this time I found the bug. Literally, I don't know how but, there was two instances for each player and while money was changing on one of them, the other were not changing so the values on the table too. That is kinda different problem other than table tho. Anyway. Many thanks. Upvoting for your efforts, but not accepting the answer sorry. – Kutay Demireren Oct 16 '15 at 01:52
  • @KutayDemireren If you used the above suggestion you probably wouldn't have had the problem. So the "bug" was in code you weren't providing, good to see that no one was going to be able to answer you question then. Glad you found the answer. You could delete the question, as it's going to be impossible to answer based your example code ;) – MadProgrammer Oct 16 '15 at 01:55