JTable soll mit Buttons befüllt werden, aber nicht in jede Zelle einer Spalte

ForenDaddy

Grünschnabel
hänge an einem problem, dass ich einfach nicht lösen kann.
ich habe eine tabelle, die ich in einer spalte mit buttons gefüllt habe, denen ich imageicons verpasst habe. sieht soweit super aus.
problem: nicht in jede zelle soll solch ein button erscheinen.
am besten wäre, wenn eine bedingung erfüllt ist, dass der button dann eben nicht eingetragen wird.
die buttons habe ich mit
Code:
colModel.getColumn(7).setCellRenderer((TableCellRenderer) new ButtonRenderer());
colModel.getColumn(7).setCellEditor(new ButtonListener(table));
erstellt.
ButtonListener und ButtonRenderer habe ich selbst erstellt.
ich kriege immer nur zwei effekte hin, entweder steht in jeder zelle das icon oder in keiner.
veränderungen im renderer haben bisher nichts gebracht.

was ich soweit rausgefunden habe, durch colmodel, holt er sich das icon und schreibt es einfach in jede zelle der spalte. so gut wie ungeachtet der if anweisung. und er holt sich das icon nur einmal und geht nicht jeden auftrag durch, um zu sehen ob die bedingung noch stimmt.
daher schlug z.b. folgender test fehl (buttonrenderer zeile 15):
Code:
boolean schalter = false;
....
if ( column == 1 && schalter ) {
.....
trotzdem zeichnet er immer jede zelle.

daher meine frage: kann man den inhalt einer zelle komplett loeschen, nach dem die tabelle gezeichnet wurde? setvalueat geht, aber das aendert nur die schrift am, bei mir, darunter liegenden button. ich möchte den button selber aber entfernen.
so könnte ich die unerwünschten buttons vielleicht nachträglich entfernen.


Programmausschnitt:
Code:
.................
String[] colNames = {
            // Spaltenueberschriften
                "Auftragsnr",
                "Statusmeldung",
                "Abrechnung",
                "Übernahmeort",
                "Übernahmezeit",
                "Abgabeort",
                "Abgabezeit",
                "Info",
                ""
            };
            DefaultTableModel model = new DefaultTableModel( colNames, 0 );

            for( Auftrag auftrag : auftraege ) {
model.addRow( new String[] { auftrag.auftragsNr,
                                                "i",
                                                "€",
                                                auftrag.uebernahmeStadt,
                                                test.getUhrzeit( auftrag.uebernahmePlanungAnkunft ),
                                                auftrag.abgabe,
                                                test.getUhrzeit( auftrag.abgabePlanungAnkunft ),
                                                "!",
                                                "zum Auftrag" } );
}

JTable table = new JTable(model) {
                // Deaktiviert die Editierbarkeit der Zellen von Spalte 0 bis 4
                // 5. Spalte bleibt editierbar, sonst funktionieren die Buttons nicht mehr.
                public boolean isCellEditable(int x, int y) {
                    if ( y == 1 || y == 2 || y == 7 || y == 8 ) {
                        return true;
                    }
                    return false;
                }
            };
TableColumnModel colModel = table.getColumnModel();
colModel.getColumn(8).setCellRenderer((TableCellRenderer) new ButtonRenderer());
colModel.getColumn(8).setCellEditor(new ButtonListener(table));
table.setRowHeight(30);
table.setCellSelectionEnabled(true);
Dimension d = table.getPreferredSize();
table.setPreferredScrollableViewportSize(d);
..............

ButtonListener:
Code:
class ButtonListener extends AbstractCellEditor implements TableCellEditor,
                                                         ActionListener {
        JTable table;
        JButton button = new JButton();
        NumberFormat nf = NumberFormat.getCurrencyInstance();
        int clickCountToStart = 1;

        public ButtonListener(JTable table) {
            this.table = table;
            button.addActionListener(this);
        }

        public void actionPerformed(ActionEvent e) {
            int zeile = table.getEditingRow();
            int spalte = table.getEditingColumn();

            // Auftrag anzeigen
            if ( spalte == 8 ) {
                for ( Auftrag auftrag : auftraege ) {
                    if ( auftrag.auftragsNr.equals( table.getValueAt(zeile, 0).toString() ) ) {
                            GUIoverview.getInstance().replacePanel( new GUIauftrag_UN( auftrag, GUIauftrag_UN.UEBERNAHME ) );
                    }
                }
}
.....................

kompletter ButtonRenderer:
Code:
class ButtonRenderer implements TableCellRenderer {
        JButton button = new JButton();
        BufferedImage image;
        int zellenBreite = 0;
        int zellenHoehe = 0;


        public Component getTableCellRendererComponent(JTable table,
                                                       Object value,
                                                       boolean isSelected,
                                                       boolean hasFocus,
                                                       int row, int column) {

            zellenHoehe = table.getRowHeight( column );
            if ( column == 1 ) {
          String fahrauftragBemerkung = "";
                for ( Auftrag auftrag : FCP_System.auftraege ) {
                    if ( table.getModel().getValueAt( row, 0 ).equals( auftrag.auftragsNr ) ) {
                        fahrauftragBemerkung = auftrag.fahrauftragBemerkung;
                    }
                }
                if ( !fahrauftragBemerkung.equals( "" ) ) {
                    zellenBreite = table.getColumn( "Info" ).getWidth();
                    image = new Bilder( new Auftrag() ).loadImage( FCP_System.ICON_AUSRUFEZEICHEN_RED );
                    //image = loadImage( image, FCP_System.ICON_AUSRUFEZEICHEN_RED );
                    // Berechnet die Breite des neuen Bildes im richtigen Seitenverhaeltnis
                    double bildBreite = (double)image.getWidth() * ( (double)zellenHoehe / (double)image.getHeight() );
                    // Skaliert das Icon passend auf die Zelle

                    int neueBildBreite = (int) (bildBreite * 0.8);
                    int neueBildHoehe = (int) (zellenHoehe * 0.8);

                    int type = image.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : image.getType();
                    BufferedImage resizedImage = new BufferedImage(neueBildBreite, neueBildHoehe, type);
                    Graphics2D g = resizedImage.createGraphics();
                    g.drawImage(image, 0, 0, neueBildBreite, neueBildHoehe, null);
                    g.dispose();

                    JButton button = new JButton( new ImageIcon( resizedImage ) );
                    //button = new JButton( new ImageIcon( image.getScaledInstance( (int) (bildBreite * 0.8), (int) (zellenHoehe * 0.8), image.SCALE_SMOOTH ) ) );
                    //button.setPressedIcon( new ImageIcon( image.getScaledInstance( (int) (bildBreite * 0.8), (int) (zellenHoehe * 0.8), image.SCALE_SMOOTH ) ) );
                    button.setPressedIcon( new ImageIcon( resizedImage ) );
                    // Button wird durchsichtig
                    button.setContentAreaFilled( false );
                    // Buttonrand wird durchsichtig
                    button.setBorderPainted( false );
                    return button;
 }
            } else if ( column != 7 ) {
                JButton button = new JButton();
                button.setText(value.toString());
                return button;
            }
/** @todo Button wird trotzdem noch sichtbar, wenn er geklickt wird. */
            JButton button = new JButton();
            button.setContentAreaFilled( false );
            button.setBorderPainted( false );
            button.setEnabled( false );
            button.setVisible( false );
            return button;
        }
 
Zuletzt bearbeitet:
Du fuegst doch mittels
Java:
 if ( column == 1 ) {
in der getTableCellRendererComponent die Buttons zu?
Wieso ueberpruefst du nicht auch die Zeile um genau in den Zellen die Buttons zu haben wo du moechtest?
 
genau das funktioniert nicht.
colmodel holt sich den button, so wie es aussieht, nur einmal und fuegt sie einfach in alle zellen der spalte ein. er ueberprueft also ueberhaupt nicht zeilenweise, ob meine bedingungen noch zutreffen.

daher meine frage:
- gibt es eine möglichkeit den inhalt einer zelle zu leeren oder einen anderen button zu setzen, so dass man nicht mehr die möglichkeit hat einen button zu drücken. setEnabled(false) oder irgend etwas.
- gibt es noch andere möglichkeiten buttons mit icons in eine tabelle zu bekommen, bei der man aber zeilen-/zellenweise vorgehen kann? z.b. wenn man nur einen einzigen button in einer einzigen zelle haben möchte.
 
Dann setze doch für das Column einen Datentyp (z.B. boolean wenn es nur 2 Optionen gibt, ansonsten irgendwas, das von enum erbt) und der TableCellRenderer muss nur noch den Wert der Zelle auslesen.
Du könntest z.B. für "true" einen JButton darstellen, für "false" einfach eine weiße Fläche.
 
ok, ich erkläre es noch einmal. er wertet NICHT zeile für zeile aus.
das mit einem boolean wert habe ich schon versucht. auch das auswerten des zelleninhalts habe ich schon gemacht. ich habe einen text gesetzt wenn das icon kommen soll und einen anderen wenn es nicht kommen soll bzw. ein anderes symbol.
das ist colmodel egal.
er schaut ob in der ersten zeile die if bedingung stimmt, dann rattert er einfach jede zelle runter.
er prüft nicht erneut, er schaut nicht was in den einzelnen zellen, er geht nicht über los.
er marschiert einfach bis zum ende durch.
 
Hallo,

erstmal, wir achten hier im Forum eine gewisse Form, deshalb möchte ich dich doch bitten auf deine Groß- und Kleinschreibung zu achten.

Nur um sicher zu gehen. Du hast eine Spalte mit Buttons in deiner Table, es soll aber nicht in jeder Zeile ein Button dargestellt werden und nur dass nicht in jeder Zeile ein Button dargestellt wird, bekommst du nicht hin.
Ist das so korrekt?

Poste mal bitte den kompletten ButtonRenderer.

Warum möchtest du eigentlich einen Button in dem Renderer haben? Du setzt setContentAreaFilled und setBorderPainted auf false. Damit sieht der Button aus, wie ein normales Label. Dann kannst du auch direkt ein JLabel nehmen, da ein Button in einem Renderer keine Funktion hat.

Gruß

Sascha
 
Ich werde mich befleissigen, die Form zu wahren.
Nicht in allen Foren wird darauf geachtet und so schleicht sich der Schlendrian ein.

Deine Annahme ist richtig. Genau das ist mein Problem.

ButtonRenderer habe ich oben komplett gepostet.

Ich zäume das Pferd mal von der anderen Seite auf. Ich möchte ein Icon haben, das wie ein Button funktioniert. Das Icon soll also ein actionPreformed() ausführen können, wenn ich darauf klicke.
Dabei soll zu jedem Zeitpunkt, das Icon als solches sichtbar sein. Am liebsten natürlich wenn ich klicke etwas anders oder wenn es nicht klickbar ist, wieder ein anderes Icon. Aber in jedem Fall soll es ein einheitliches Design haben.
Die momentane Umsetzung ist deshalb so, weil ich einfach einen Beispielcode gefunden habe, der funktionierte. Warum und weshalb, habe ich nicht hinterfragt.
Wenn es also eine andere Möglichkeit gibt, immer her damit. Ich habe da keine fest gefügten Vorstellungen.
 
Es wird in jeder Zeile ein Button dargstellt, weil du immer ein Button zurück gibst. Wenn du möchtest, dass kein Button da ist, musst du für diese Zeile etwas anderes zurück geben, wie beispielsweise ein JLabel. Aber du kannst halt im Renderer auch direkt ein JLabel lassen und das Icon entsprechend setzen.

Das Problem ist, dass du da reinpacken kannst was du möchtest, da die Komponenten nur dahin gezeichnet werden, haben sie keinerlei Funktion. Das heißt, dass dort auch der Listener nicht reagieren wird.

Es könnte halt funkionieren, wenn man einen Button in einen Editor packt. Dann ist nämlich wirklich die Komponente da.

Gruß

Sascha
 
STOP. Das ist genau das, was ich oben schon gesagt habe.
Ich kann nichts anderes zurückgeben pro Zeile. Das pro Zeile funktioniert nicht.
Er prüft eben nicht pro Zeile. colmodel prüft nur einmal und zwar zu Beginn und rennt dann durch.
Ich kann also für verschiedene Bedingungen oder Scenarien, verschiedene Dinge zurückgeben, es funktioniert nicht. Er wird immer die erste Bedinung nehmen und immer das Selbe machen, ohne erneut zu prüfen.

Deshalb noch einmal meine Frage:
Kann man ausser über colmodel eine Zelle, mit etwas Ähnlichem wie einem Button, noch befüllen?
 
Wenn du in dem ButtonRenderer beispielsweise sowas machst

Java:
if(row % 2 == 1)
    return Button;
else
    return label;

hast du jede zweite Zeile einen Button und jede zweite ein Label.
Das ist auch das was ich gesagt hab.

Gruß

Sascha
 
Zurück