JTable रेंडर कभी-कभी प्रतिपादन रोकता है लेकिन विंडो आकार बदलने पर फिर से शुरू होता है

मुझे अपने कस्टम जेटीबल और कस्टम टेबल रेंडरर के साथ एक रहस्यमय समस्या मिली है। 95% -99,99% में यह पूरी तरह से काम करता है, लेकिन कभी-कभी रेंडरर सिर्फ अपना काम करना बंद कर देता है, और तालिका के एक हिस्से को छोड़ देता है (जो जेएसक्रोलपैन के अंदर है) खाली है।

The problem case looks like that: rednering has terminated to early

In all other cases, and after a slight resize of the window, the Table look like that: rendering has terminated successful

अब दोनों स्तंभों में एक TextAreaCellRenderer से जुड़ा हुआ है, जो निम्नानुसार कार्य करता है:

public class TextAreaCellRenderer extends JTextArea implements TableCellRenderer {

    private final Color evenColor = new Color(252, 248, 202);


    public TextAreaCellRenderer() {
        super();
        setLineWrap(true);
        setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
    }


    @Override
    public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int column) {
        if (isSelected) {
            setForeground(table.getSelectionForeground());
            setBackground(table.getSelectionBackground());
        } else {
            setForeground(table.getForeground());
            setBackground(table.getBackground());
            setBackground((row % 2 == 0) ? evenColor : getBackground());
        }
        setWrapStyleWord(true);
        setFont(table.getFont());
        setText((value == null) ? "" : value.toString());
        return this;
    }
}

मुझे सामग्री के आधार पर सेल के हाइट की गणना करने में सक्षम होने के लिए जेटीबल की डोलआउट विधि को ओवरराइड करना होगा। कस्टम टेबल इस तरह दिखता है:

public class MediaMetaDataTable extends JTable {

    @Override
    public void doLayout() {
        TableColumn col = getColumnModel().getColumn(1);
        for (int row = 0; row < getRowCount(); row++) {
            Component c = prepareRenderer(col.getCellRenderer(), row, 1);
            if (c instanceof JTextArea) {
                JTextArea a = (JTextArea) c;
                int h = getPreferredHeight(a) + getIntercellSpacing().height;
                if (getRowHeight(row) != h) {
                    setRowHeight(row, h);
                }
            }
        }
        super.doLayout();
    }


    private int getPreferredHeight(final JTextComponent c) {
        Insets insets = c.getInsets();
        View view = c.getUI().getRootView(c).getView(0);
        int preferredHeight = (int) view.getPreferredSpan(View.Y_AXIS);
        return preferredHeight + insets.top + insets.bottom;
    }
}

निम्न पैरामीटर के साथ तालिका को तुरंत चालू किया जाता है:

metaTable = new MediaMetaDataTable();
metaTable.setModel(new MediaMetaDataTableModel());
metaTable.setEnabled(false);
metaTable.setShowGrid(false);
metaTable.setTableHeader(null);
metaTable.getColumnModel().getColumn(0).setCellRenderer(new TextAreaCellRenderer());
metaTable.getColumnModel().getColumn(1).setCellRenderer(new TextAreaCellRenderer());
metaTable.setPreferredScrollableViewportSize(new Dimension(-1, -1));
metaTable.setShowHorizontalLines(false);
metaTable.setShowVerticalLines(false);

प्रत्येक बार डेटा दिखाने के लिए मैं अंतर्निहित मॉडल डेटा को बदलकर तालिका अद्यतन करता हूं:

List metaInformation = mediaSearchHit.getMetaInformation();
        if (metaInformation != null) {
            ((MediaMetaDataTableModel) metaTable.getModel()).replaceMetaInfos(metaInformation);
        }

अद्यतन पर मॉडल खुद ही एक तालिका डेटा बदलता है घटना:

public class MediaMetaDataTableModel extends AbstractTableModel {

    private List metaInfos = new LinkedList();

    public static final int COL_INDEX_NAME = 0;
    public static final int COL_INDEX_VALUE = 1;


    public void replaceMetaInfos(final List metaInfos) {
        this.metaInfos = null;
        this.metaInfos = metaInfos;
        fireTableDataChanged();
    }
...

अब क्या किसी के पास कोई विचार है, वर्णित प्रतिपादन समस्या का कारण क्या है?

किसी भी सलाह के लिए धन्यवाद।

0
अब क्या किसी के पास कोई विचार है, वर्णित प्रतिपादन समस्या का कारण क्या है? == एसएससीसीई, लघु, रननेबल, जेटीबल के लिए हार्डकोडेड मूल्य के साथ संकलित, बीटीडब्ल्यू यस्टेडे से पूछा गया और उत्तर प्रश्न
जोड़ा लेखक mKorbel, स्रोत
और JTextArea को विस्तारित करने के बजाय स्थानीय चर बनाने के लिए, doLayout बहुत familair है, महत्वपूर्ण गलती सेट के लिए क्या कारण हैप्रदर्शित स्क्रॉल करने योग्य दृश्य दृश्य (नया आयाम (-1, -1)) ;, सारणीटेबल मॉडेल को कैसे लिखना है, यह खोजना शुरू करें यदि बाकी आपके कोड को फिसल गया जैसा ही है आपने यहां दिखाया
जोड़ा लेखक mKorbel, स्रोत
बेहतर सहायता के लिए, एक SSCCE पोस्ट करें।
जोड़ा लेखक Andrew Thompson, स्रोत
कभी-कभी गलत सिंक्रनाइज़ेशन का सुझाव देता है।
जोड़ा लेखक trashgod, स्रोत

2 उत्तर

अगर मुझे लगता है कि मैं कहूंगा कि यह एक अनिवार्य समस्या हो सकती है। क्या आप जीयूआई-थ्रेड में सबकुछ कर रहे हैं? यदि हां, तो यह एक अनिवार्य समस्या नहीं हो सकती है। अन्यथा Thital.InvokeLater() के साथ सब कुछ कॉल करने का प्रयास करें, यदि आप परीक्षण के लंबे समय बाद त्रुटि का सामना नहीं करते हैं, तो आपको समस्या का कारण पता है।

दूसरे चरण में आप जांच करेंगे कि इनवोकेलेटर() के साथ कॉल करने के लिए जहां आवश्यक है और कहां नहीं है (क्योंकि आपको हर समय ऐसा नहीं करना चाहिए, क्योंकि इससे बहुत खराब प्रदर्शन होता है।

जैसा कि मैंने कहा, बस एक जंगली अनुमान ... यह सिर्फ एक और बग हो सकता है। क्या आप जावा 7 का उपयोग कर रहे हैं? स्विंग में जावा 7 कोड के साथ लाखों कीड़े हैं (केवल ऑरैकल से आए सभी कोड)।

1
जोड़ा

मुझे सक्षम होने के लिए JTable की doLayout विधि को ओवरराइड करना होगा   सामग्री के आधार पर सेल के हाइट की गणना करने के लिए।

इस लक्ष्य को प्राप्त करने के लिए doLayout() विधि को ओवरराइड करने की आवश्यकता नहीं है। मुझे लगता है कि ऐसा करने का सबसे आसान तरीका सेल सामग्री को JPanel में BorderLayout के साथ प्रस्तुत करने के लिए उपयोग किए गए टेक्स्ट क्षेत्र को जोड़कर और पैनल के पसंदीदा आकार के आधार पर पंक्ति ऊंचाई सेट करना है । इस प्रकार लेआउट प्रबंधक आपके लिए चाल करेगा और सभी सेल की सामग्री दिखाई देगी:

@Override
public Component getTableCellRendererComponent(...) {
    ...
    JPanel contentPane = new JPanel(new BorderLayout());            
    contentPane.add(this);
    table.setRowHeight(row, contentPane.getPreferredSize().height);//sets row's height
    return contentPane;
}

जैसा कि @mKorbel ने इंगित किया है, रेंडरर को JTextArea से विस्तारित करने की आवश्यकता नहीं है: एक एकल चर काम करेगा। इसे ध्यान में रखते हुए अपने काम के आधार पर इस कार्यान्वयन पर नज़र डालें:

class TextAreaRenderer implements TableCellRenderer {

    private JTextArea renderer;
    private final Color evenColor = new Color(252, 248, 202);

    public TextAreaRenderer() {
        renderer = new JTextArea();            
        renderer.setLineWrap(true);
        renderer.setWrapStyleWord(true);
        renderer.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        if (isSelected) {
            renderer.setForeground(table.getSelectionForeground());
            renderer.setBackground(table.getSelectionBackground());
        } else {
            renderer.setForeground(table.getForeground());
            renderer.setBackground((row % 2 == 0) ? evenColor : table.getBackground());
        }            
        renderer.setFont(table.getFont());
        renderer.setText((value == null) ? "" : value.toString());
        JPanel contentPane = new JPanel(new BorderLayout());            
        contentPane.add(renderer);
        table.setRowHeight(row, contentPane.getPreferredSize().height);//sets row's height
        return contentPane;
    }

}

स्क्रीनशॉट

enter image description here

1
जोड़ा
आपके समय के लिए धन्यवाद और Delcio बर्दाश्त! आपका समाधान ठीक है। एकमात्र मुद्दा यह है कि परिणाम कभी-कभी परिणाम सेट को पुन: सक्रिय करते समय अर्जित होता है, लेकिन यह लंबे समय तक नहीं रहता है, वहां सीम को रीफ्रेश करने के लिए सीम होता है। दृश्यों के पीछे शायद कुछ प्रकार की घटनाओं को संभालने का कारण, जो परिणामों को अद्यतन करता है। इस मामले में एसएससीसीई प्रदान करने का कारण भी बहुत कठिन होगा। वैसे भी, आपका समाधान एक बड़ी मदद है! धन्यवाद!
जोड़ा लेखक Macilias, स्रोत
@Macilias आपका स्वागत है! मुझे खुशी है कि यह आपकी मदद करता है :) जैसा कि आप कहते हैं कि इस व्यवहार के कारण से ईवेंट हैंडलिंग के साथ कुछ करना पड़ सकता है। बस इवेंट डिस्पैचिंग थ्रेड में मॉडल में पंक्तियों को जोड़ना सुनिश्चित करें, उदाहरण के लिए स्विंगवर्कर का उपयोग करके उदाहरण के रूप में यहां । उदाहरण JComboBox में आइटम जोड़ने के बारे में है लेकिन वास्तव में यह JTable (या किसी भी स्विंग घटक) पर लागू होता है।
जोड़ा लेखक dic19, स्रोत