Edycja komórek w JTable.

0

Witam, mam problem z edycją komórek w mojej Tabeli (JTable), chodzi o to że po edycji, zmienione dane w komórce się nie zapisują. Jak zrobić, żeby dane zapisywały się po edycji np. do ArrayListy, albo tablicy??

0

Nadpisz w klasie z modelem dziedziczącej po DefaultTableModel (lub w klasie z tabelą dziedziczącej po JTable) metodę setValuAt(Object value, int wiersz, int kolumna). value, to to co wpisał użytkownik podczas edycji, wiersz i kolumna to współrzędne edytowanej komórki. Jeżeli nadpiszesz metodę w klasie dziedziczącej po JTable (a nie po modelu), to musisz uwzględnić, że współrzędne dotyczą widoku i mogą się różnić od współrzędnych w modelu jeżeli dopuszczalne jest sortowanie i przestawianie kolumn.

0

No człowieku... przydałoby się trochę kodu. Jaki masz TableModel, gdzie są te dane?
Próbowałeś

tableModel.fireTableDataChanged();

?

0

Dane przechowuję w tablicy 2-wymiarowej i w liście Array, ponieważ pobieram je z pliku, zrobiłem coś takiego

    Object[][] data;
    public Object getValueAt(int row, int col) 
    {
        return data[row][col];
    }
    public void setValueAt(Object value, int row, int col) 
    {
        data[row][col] = value;
        tablica[row][col]= (String) data[row][col];   //tablica to właśnie ta moja tablica w której przechowuję dane.
    }

Chcę po prostu żeby te dane po edycji, zapisały się w mojej tablicy, a później żeby się zaktualizowały(odpowiednie linijki) w pliku. (Np. edytuję 3 komórkę w 1 wierszu, oczywiście w programie jest indeksowanie od 0, ale to tylko dla przykładu, to dane w tablicy[1][3] się zmienią, a w pliku zaktualizuje się 3 linijka.

dodane znaczniki <code class="java"> - fp

0

W tablicy juz zakualizowałeś. Kiedy ma się aktualizować w pliku? Bez sensu jest by przepisywac cały plik po zmianie kazdej komórki. Zapisuj jak uzytkownik zamyka program. W głównym oknie:

setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);

Dodaj do okna WindowListenera, w metodzie windowClosing() zapisz nowa wersje pliku i wywołaj System.exit(0);

0

Przy wywoływaniu metod get i set mam błąd..

 
        int wiersz = tabela.getEditingRow();
        int kol = tabela.getEditingColumn();
        model.getValueAt(wiersz, kol);           // w tej linijce mam błąd Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1 czyli że coś z rozmiarem tablicy?
        model.setValueAt(dane, wiersz, kol);

dodane znaczniki <code class="java"> - fp

0

Ty nie masz wywoływać metod getValueAt i setValueAt. One zostana wywołane automatycznie. Ty je masz tylko napisać.

0

A jak dodać tego WindowListenera?
mam główną klasę Okno która dziedziczy po JFrame i implementuje ActionListenera i w niej jest wszystko co znajduje się w tym oknie, JTabela, przyciski itd.

0
addWindowListener(new WindowAdapter()
{
    public void windowClosing(WindowEvent we)
    {
         //zapisanie do pliku
         System.exit(0);
    }
});
0

Nie mam pojęcia czemu, ale ta edycja nie działa..

0
public class Okno extends JFrame implements ActionListener {
    JMenuBar menuBar;
    JMenu menuPlik, menuEdycja;
    JMenuItem mNowe, mWyjscie, mEdycja, mUsun;
    JLabel lZadania;
    JPanel pNowe;
    JTable tabela;
    JScrollPane scrollPane;
    Object[][] dane;
    int ileLinijek=0;
    String[][] tablica;
    //String[][] rowData;
    String [] kolumny= {"Data", "Godzina", "Zadanie"};
    ArrayList<String> w = new ArrayList<String>();
    DefaultTableModel model;
    
    public Okno()
    {
        setSize(700,400);
        setTitle("Terminarz zadań");
        setLayout(null);
        
        menuBar = new JMenuBar();
        menuPlik = new JMenu("Plik");
        menuEdycja = new JMenu("Edycja");
        
        lZadania = new JLabel("Twoje zadania");
        lZadania.setBounds(10,10,100,20);
        
        
        mNowe = new JMenuItem("Nowe zadanie", 'N');
        mWyjscie = new JMenuItem("Wyjście");
        mEdycja = new JMenuItem("Edytuj");
        mUsun = new JMenuItem("Usuń");
        
        menuPlik.add(mNowe);
        menuPlik.addSeparator();
        menuPlik.add(mWyjscie);
        
        
        mNowe.addActionListener(this);
        mWyjscie.addActionListener(this);
        mEdycja.addActionListener(this);
        mUsun.addActionListener(this);
        
        mNowe.setAccelerator(KeyStroke.getKeyStroke("ctrl N"));
        mWyjscie.setAccelerator(KeyStroke.getKeyStroke("ctrl X"));
        mEdycja.setAccelerator(KeyStroke.getKeyStroke("ctrl E"));
        mUsun.setAccelerator(KeyStroke.getKeyStroke("ctrl Q"));
        
        menuEdycja.add(mEdycja);
        menuEdycja.add(mUsun);
        
        setJMenuBar(menuBar);
        menuBar.add(menuPlik);
        menuBar.add(menuEdycja);
        add(lZadania);
        
        
        Odczyt();
        model = new DefaultTableModel(tablica,kolumny);
        tabela = new JTable();
        tabela.setModel(model);
        tabela.setBounds(100,100,660,300);
        tabela.getColumnModel().getColumn(0).setMinWidth(80);
        tabela.getColumnModel().getColumn(0).setMaxWidth(80);
        tabela.getColumnModel().getColumn(1).setMinWidth(120);
        tabela.getColumnModel().getColumn(1).setMaxWidth(120);
        tabela.setRowHeight(30);
        tabela.setVisible(true);
        RowSorter<DefaultTableModel> sorter = new TableRowSorter<DefaultTableModel>(model);
        tabela.setRowSorter(sorter);
        add(tabela);

        scrollPane = new JScrollPane(tabela);
        scrollPane.setBounds(10,30,660,300);
        scrollPane.setVisible(true);
        add(scrollPane);
        addWindowListener(new WindowAdapter() {
        @Override
        public void windowClosing(WindowEvent we)
        {
                 try
                {
                    FileWriter plik = new FileWriter("Zadania.txt");
                    PrintWriter pw = new PrintWriter(plik);
                    for(int i=0;i<(w.size())/3;i++)
                    {
                        for(int j=0;j<3;j++)
                        {
                            pw.println(tablica[i][j]);
                        }
                    }
                        pw.close();
                } catch (IOException ex) {
                Logger.getLogger(OknoNowe.class.getName()).log(Level.SEVERE, null, ex);
                }
         System.exit(0);
        }
        });
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Object zrodlo = e.getSource();
        
        if(zrodlo==mNowe)
        {
            OknoNowe ok = new OknoNowe();
            ok.setVisible(true);
        }
        
        if(zrodlo==mWyjscie)
            dispose();
        
        if(zrodlo==mUsun)      //Usuwanie zaznaczonego wiersza w JTabeli
        {
            int odp = JOptionPane.showConfirmDialog(null, "Czy jesteś pewny/a,"
            + " że chcesz usunąć zadanie?", "Potwierdzenie", JOptionPane.YES_NO_OPTION);
            if(odp==JOptionPane.YES_OPTION)
            {
            int wiersz = tabela.getSelectedRow();
            model.removeRow(tabela.getSelectedRow());
            int Od = wiersz*3;
            int Do = wiersz*3+3;
            w.subList(Od,Do).clear();
            for(int i=0;i<(w.size())/3;i++)
            {
                for(int j=0;j<3;j++)
                {
                    tablica[i][j] = w.get((3*i)+j);
                }
            }
                for(int i=0;i<(w.size())/3;i++)
                {
                    for(int j=0;j<3;j++)
                    {
                        System.out.println(tablica[i][j]+" ");
                    }
                }
            try
                {
                    FileWriter plik = new FileWriter("Zadania.txt");
                    PrintWriter pw = new PrintWriter(plik);
                    for(int i=0;i<(w.size())/3;i++)
                    {
                        for(int j=0;j<3;j++)
                        {
                            pw.println(tablica[i][j]);
                        }
                    }
                        JOptionPane.showMessageDialog(null, "Wiersz usunięto pomyślnie :)");
                        System.out.print("Wielkośc array "+w.size()+"\n wielkosc tablicy " +tablica.length+"\n");
                        pw.close();
                } catch (IOException ex) {
                Logger.getLogger(OknoNowe.class.getName()).log(Level.SEVERE, null, ex);
                }
            }else if(odp==JOptionPane.NO_OPTION)
            {
            }
        }
    }
    
    protected void Odczyt()             //Czytanie z pliku do ArrayListy a później przepisanie do tablicy
    {
        try {
            File plik = new File("Zadania.txt");
            Scanner skaner = new Scanner(plik);
            while(skaner.hasNext())
            {
                ileLinijek++;
                skaner.nextLine();
            }
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Okno.class.getName()).log(Level.SEVERE, null, ex);
        }
        System.out.print("Ilosc linijek: "+(ileLinijek-1)/3+" ");
        try {
            File plik = new File("Zadania.txt");
            Scanner skaner = new Scanner(plik);
            /*for(int i=0;i<(ileLinijek-2)/3;i++)
                for(int j=0;j<3;j++)*/
            while(skaner.hasNext())
            {
                w.add(skaner.nextLine());
            }
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Okno.class.getName()).log(Level.SEVERE, null, ex);
        }
        tablica = new String[w.size()/3][3];
            System.out.print("wielkosc array "+w.size()+"\n");
        for(int i=0;i<w.size()/3;i++)
        {
            for(int j=0;j<3;j++)
            {
                tablica[i][j] = w.get((3*i)+j);
            }
        }
    
        for(int i=0;i<w.size()/3;i++)
        {
            for(int j=0;j<3;j++)
            {
                System.out.println(tablica[i][j]);
            }
        }
    }
    
    public Object getValueAt(int row, int col) 
    {
        return dane[row][col];
    }
    public void setValueAt(Object value, int row, int col) 
    {
        dane[row][col] = value;
        tablica[row][col]= (String) dane[row][col];
    }
}
0
        addWindowListener(new WindowAdapter() {
        @Override
        public void windowClosing(WindowEvent we)             //zapis
        {
                 try
                {
                    FileWriter plik = new FileWriter("Zadania.txt");
                    PrintWriter pw = new PrintWriter(plik);
                    for(int i=0;i<(w.size())/3;i++)
                    {
                        for(int j=0;j<3;j++)
                        {
                            pw.println(tablica[i][j]);
                        }
                    }
                        pw.close();
                } catch (IOException ex) {
                Logger.getLogger(OknoNowe.class.getName()).log(Level.SEVERE, null, ex);
                }
         System.exit(0);
        }
        });



    public void setValueAt(Object value, int row, int col)
    {
        dane[row][col] = value;
        tablica[row][col]= (String) dane[row][col];
    }
0

A gdzie jest

setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
0

W 2 klasie o nazwie Test gdzie jest tylko metoda main w której mam

    public static void main(String[] args)
    {
        Okno o = new Okno();
        o.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        o.setVisible(true);
    }
0

Napisz klasę, która dziedziczy po DefaultTableModel, w niej umieść metody setValueAt i getValueAt. Jak zrobisz z niej klasę wewnetrzną, to nie będziesz musiał niczego przekazywać.

class Model extends DefaultTableModel
{
    ...
}
...
model = new Model();
tabela = new JTable(model);
0

ale ona musi być w oddzielnym pliku czy nie??

0

Klasa wewnętrzna w osobnym pliku?

public class Okno extends JFrame implements ActionListener {
...
    class Model extends DefaultTableModel
    {
    }
}
0

Wstawiłem do konstruktora Okno i wyskakuje błąd

found: java.lang.String[][],java.lang.String[]
reason: actual and formal argument lists differ in length

w tej linijce

model = new Model(tablica,kolumny);
0

Jak zrobisz z niej klasę wewnetrzną, to nie będziesz musiał niczego przekazywać

model = new Model();

0

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0 >= 0
at java.util.Vector.elementAt(Vector.java:470)
at javax.swing.table.DefaultTableColumnModel.getColumn(DefaultTableColumnModel.java:294)
at Okno.<init>(Okno.java:118)
at Test.main(Test.java:16)

0

Trochę przesadziłem, że niczego nie trzeba przekazywać.

    model = new Model(kolumny,w.size()/3);
    tabela = new JTable(model);
    ...
    class Model extends DefaultTableModel
    {
        public Model(Object[] columns,int rowCount)
        {
            super(columns,rowCount);
        }
        public Object getValueAt(int row, int col) 
        {
            return tablica[row][col];
        }
        public void setValueAt(Object value, int row, int col) 
        {
            tablica[row][col] = (String) value;
        }
    }
0

Ok zmienia, ale teraz problem bo w nazwach kolumn jest jakieś "java.lang..." bla bla....

0

W ogóle cała tabela się pokićkała, nie wczytuje z wszystkiego z pliku.

0

I jednak muszę mieć zapis do pliku od razu po edycji każdej komórki, a nie przy wyłączaniu, ponieważ mam drugie okienko w którym wypełniam formularz i zapisuje właśnie do pliku i zapisuje się ale dopóki nie zamknę tego pierwszego głównego okienka, jak zamknę to po prostu wstawia to co było wcześniej (zapamiętane już przez tablicę).

0

Ok, już sobie poradziłem z tymi kolumnami i zapisem, wszystko jest ok, ale jeszcze mam pytanie bo za każdym razem gdy w tej 2 ramce wypełniam formularz i zapisuje, muszę zamknąć i włączyć aplikację żeby dane pojawiły się w tabeli i chciałbym się dowiedzieć czy da się tak zrobić żebym nie musiał wyłączać i włączać aplikacji?

0

Zmodyfikuj dane w zmiennej tablica i wywołaj (odpowiednią) metodę fireTable....

0

właśnie tablica się odświeża ładnie, a tabela coś nie chce...

1 użytkowników online, w tym zalogowanych: 0, gości: 1