سؤال

حسنًا، أعرف كيفية إنشاء مكون JComponent مخصص بسيط.أعرف كيفية تجاوز TableCellRenderer.يبدو أنني لا أستطيع الجمع بين الاثنين.

وهنا عينة JComponent صنعت:

public static class BarRenderer extends JComponent
{
    final private double xmin;
    final private double xmax;
    private double xval;
    public BarRenderer(double xmin, double xmax)
    {
        this.xmin=xmin;
        this.xmax=xmax;
    }

    @Override protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Rectangle r = g.getClipBounds();
        g.drawRect(r.x, r.y,
                (int)(r.width * ((xval-xmin)/(xmax-xmin))), r.height);
    }

    public void setXval(double x) { 
        this.xval = x;
        repaint();
    }
    public double getXval() { return xval; }
}

إنه يعمل بشكل جيد باعتباره JComponent مستقل.أنا أتصل setXval(something) ويتم تحديثه على ما يرام.(يحرر:لدي Swing Timer يقوم بتحديث البيانات بشكل دوري)

لكن إذا كان هذا المكون شيئًا أرجعه في TableCellRenderer.getTableCellRendererComponent()، فإنه يُعاد رسمه فقط عندما أنقر على الخلية المعنية.ما يعطي؟يجب أن أترك شيئًا بسيطًا حقًا.

هل كانت مفيدة؟

المحلول

لأسباب تتعلق بالأداء إعادة استعمال وJTable مكونات العارض لرسم خلايا متعددة - لذلك عندما ترى المكون في JTable أنه ليس هناك في الواقع بالمعنى التقليدي للمكون في حاوية التي هي موجودة في الموقع. وهذا يعني أن يدعو إعادة رسم () على عنصر العارض لا يفعل شيئا.

والخيار الأكثر فعالية سيكون لتخزين قيمة عدد صحيح من شريط في TableModel الخاص بك. سوف TableCellRenderer الخاص بك، ثم ننظر بشيء من هذا القبيل:

public class BarTableCellRenderer implements TableCellRenderer {
    private final BarRenderer rendererComponent = new BarRenderer(0, 10);

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        rendererComponent.setXval((Integer)value);
        return rendererComponent;
    }
}

وثم هل يمكن تغيير عدد صحيح في TableModel وأنها قد تؤدي إلى إعادة رسم شريط (قد تحتاج إلى TableModel.fireTableCellUpdated تعتمد على تنفيذ TableModel الذي تستخدمه).

نصائح أخرى

لقد ساعدتما كلاكما (روس هايوارد وأندرو)، وكان المفتاح في الأساس هو القيام بما يلي:

  • قم بتخزين الحالة لتكون مرئية في TableModel نفسه، وليس في العارض
  • تأكد من أنه عندما تتغير حالة TableModel، fireTableCellUpdated() يسمى
  • لدى فقط واحد كائن TableCellRenderer و واحد JComponent لعمودي المخصص (وليس واحدًا لكل خلية)
    • داخل TableCellRenderer.getTableCellRendererComponent() تخزين حالة الخلية لأغراض العرض بعد فترة وجيزة (التخزين طويل المدى موجود في TableModel)
    • قم بتوفير هذه الحالة إلى JComponent
    • إرجاع JComponent
    • تجاوز JComponent.PaintComponent()
  • أحد الاحتمالات الملائمة هو أن يقوم عارض مخصص بتوسيع JComponent وتنفيذ TableCellRenderer، ثم إدخاله TableCellRenderer.getTableCellRendererComponent() تقوم بتخزين حالة الخلية و return this;

إليك المقتطف ذو الصلة من الكود الخاص بي والذي يعمل الآن:

class TraceControlTableModel extends AbstractTableModel {
    /* handle table state here */

    // convenience method for setting bar value (table model's column 2)
    public void setBarValue(int row, double x)
    {
        setValueAt(x, row, 2);
    }
}

// one instance of BarRenderer will be set as the
// TableCellRenderer for table column 2
public static class BarRenderer extends JComponent 
    implements TableCellRenderer 
{
    final private double xmin;
    final private double xmax;
    private double xval;
    public BarRenderer(double xmin, double xmax)
    {
        super();
        this.xmin=xmin;
        this.xmax=xmax;
    }

    @Override protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Rectangle r = g.getClipBounds();
        g.drawRect(r.x, r.y,
                (int)(r.width * ((xval-xmin)/(xmax-xmin))), r.height);
    }

    @Override
    public Component getTableCellRendererComponent(JTable arg0,
            Object value, 
            boolean isSelected, boolean hasFocus,
            int row, int col)
    {
        // save state here prior to returning this object as a component
        // to be painted
        this.xval = (Double)value;
        return this;
    }
}

إذا قمت بإجراء طاولة المفاوضات مع ويقول 3 صفوف، ولكل منها Xval مختلفة، ثم أنها لا برنامج العرض في البداية بشكل صحيح، وهذا يعني كل خلية لديها شريط أبحث مختلف؟

وعندما تقول أنها لا إعادة رسم إلا إذا كنت فوقه، وقد حدث شيء إلى البيانات الأساسية الخاصة بك ينبغي أن تسببت في العرض المرئي للبيانات (شريط المقدمة) لتغيير؟

إذا تغيرت البيانات، ولكن الجدول لا immediatley إعادة تقديم، ثم أود أن أقول إن TableModel الخاص بك لا يعمل بشكل صحيح.

والكامنة وراء تغير البيانات -> التغييرات TableModel -> حرائق TableModelEvent -> إعادة يجعل JTable

ونظرة على TableModel tuturial: HTTP: / /java.sun.com/docs/books/tutorial/uiswing/components/table.html#data

للتأكد من انك تفعل كل شيء الصحيح.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top