سؤال

انا املك JComboBox ويرغب في الحصول على فاصل في قائمة العناصر.كيف أفعل هذا في جافا؟

أحد السيناريوهات النموذجية حيث يكون ذلك مفيدًا عند إنشاء مربع تحرير وسرد لاختيار عائلة الخط؛يشبه التحكم في تحديد عائلة الخطوط في Word وExcel.في هذه الحالة، أود أن أعرض الخطوط الأكثر استخدامًا في الأعلى، ثم الفاصل وأخيرًا جميع عائلات الخطوط الموجودة أسفل الفاصل بالترتيب الأبجدي.

هل يمكن لأي شخص مساعدتي في كيفية القيام بذلك أم أن هذا غير ممكن في Java؟

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

المحلول

يوجد برنامج تعليمي قصير جدًا يحتوي على مثال يوضح كيفية استخدام ListCellRenderer المخصص على Java2s http://www.java2s.com/Code/Java/Swing-Components/BlockComboBoxExample.htm

يتضمن ذلك بشكل أساسي إدراج عنصر نائب معروف في نموذج قائمتك وعندما تكتشف العنصر النائب في ListCellRenderer، فإنك تقوم بإرجاع مثيل "new JSeparator(JSeparator.HORIZONTAL)"

نصائح أخرى

بحلول الوقت الذي كتبت فيه الكود أدناه واختبرته، ربما حصلت على الكثير من الإجابات الأفضل...
لا أمانع لأنني استمتعت بالتجربة/التعلم (ما زال أخضر قليلاً على جبهة التأرجح).

[تحرير] بعد ثلاث سنوات، أصبحت أقل خضرة بعض الشيء، وأخذت في الاعتبار الملاحظات الصحيحة لبوبندرو.ليس لدي أي مشكلة في التنقل الرئيسي الذي يعمل فقط (ربما كانت مشكلة في إصدار JVM؟).لقد قمت بتحسين العارض لإظهار التمييز.وأنا أستخدم رمزًا تجريبيًا أفضل.ربما تكون الإجابة المقبولة أفضل (أكثر معيارًا)، وربما تكون الإجابة المقبولة أكثر مرونة إذا كنت تريد فاصلًا مخصصًا...

الفكرة الأساسية هي استخدام العارض لعناصر مربع التحرير والسرد.بالنسبة لمعظم العناصر، فهي عبارة عن JLabel بسيط يحتوي على نص العنصر.بالنسبة للعنصر الأخير/الأكثر استخدامًا، أقوم بتزيين JLabel بحد مخصص يرسم خطًا في أسفله.

import java.awt.*;
import javax.swing.*;


@SuppressWarnings("serial")
public class TwoPartsComboBox extends JComboBox
{
  private int m_lastFirstPartIndex;

  public TwoPartsComboBox(String[] itemsFirstPart, String[] itemsSecondPart)
  {
    super(itemsFirstPart);
    m_lastFirstPartIndex = itemsFirstPart.length - 1;
    for (int i = 0; i < itemsSecondPart.length; i++)
    {
      insertItemAt(itemsSecondPart[i], i);
    }

    setRenderer(new JLRenderer());
  }

  protected class JLRenderer extends JLabel implements ListCellRenderer
  {
    private JLabel m_lastFirstPart;

    public JLRenderer()
    {
      m_lastFirstPart = new JLabel();
      m_lastFirstPart.setBorder(new BottomLineBorder());
//      m_lastFirstPart.setBorder(new BottomLineBorder(10, Color.BLUE));
    }

    @Override
    public Component getListCellRendererComponent(
        JList list,
        Object value,
        int index,
        boolean isSelected,
        boolean cellHasFocus)
    {
      if (value == null)
      {
        value = "Select an option";
      }
      JLabel label = this;
      if (index == m_lastFirstPartIndex)
      {
        label = m_lastFirstPart;
      }
      label.setText(value.toString());
      label.setBackground(isSelected ? list.getSelectionBackground() : list.getBackground());
      label.setForeground(isSelected ? list.getSelectionForeground() : list.getForeground());
      label.setOpaque(true);

      return label;
    }
  }
}

فئة الفاصل، يمكن أن تكون سميكة، مع لون مخصص، وما إلى ذلك.

import java.awt.*;
import javax.swing.border.AbstractBorder;

/**
 * Draws a line at the bottom only.
 * Useful for making a separator in combo box, for example.
 */
@SuppressWarnings("serial")
class BottomLineBorder extends AbstractBorder
{
  private int m_thickness;
  private Color m_color;

  BottomLineBorder()
  {
    this(1, Color.BLACK);
  }

  BottomLineBorder(Color color)
  {
    this(1, color);
  }

  BottomLineBorder(int thickness, Color color)
  {
    m_thickness = thickness;
    m_color = color;
  }

  @Override
  public void paintBorder(Component c, Graphics g,
      int x, int y, int width, int height)
  {
    Graphics copy = g.create();
    if (copy != null)
    {
      try
      {
        copy.translate(x, y);
        copy.setColor(m_color);
        copy.fillRect(0, height - m_thickness, width - 1, height - 1);
      }
      finally
      {
        copy.dispose();
      }
    }
  }

  @Override
  public boolean isBorderOpaque()
  {
    return true;
  }
  @Override
  public Insets getBorderInsets(Component c)
  {
    return new Insets(0, 0, m_thickness, 0);
  }
  @Override
  public Insets getBorderInsets(Component c, Insets i)
  {
    i.left = i.top = i.right = 0;
    i.bottom = m_thickness;
    return i;
  }
}

فئة الاختبار:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;


@SuppressWarnings("serial")
public class TwoPartsComboBoxDemo extends JFrame
{
  private TwoPartsComboBox m_combo;

  public TwoPartsComboBoxDemo()
  {
    Container cont = getContentPane();
    cont.setLayout(new FlowLayout());

    cont.add(new JLabel("Data: ")) ;

    String[] itemsRecent = new String[] { "ichi", "ni", "san" };
    String[] itemsOther = new String[] { "one", "two", "three" };
    m_combo = new TwoPartsComboBox(itemsRecent, itemsOther);

    m_combo.setSelectedIndex(-1);
    cont.add(m_combo);
    m_combo.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent ae)
      {
        String si = (String) m_combo.getSelectedItem();
        System.out.println(si == null ? "No item selected" : si.toString());
      }
    });

    // Reference, to check we have similar behavior to standard combo
    JComboBox combo = new JComboBox(itemsRecent);
    cont.add(combo);
  }

  /**
   * Start the demo.
   *
   * @param args   the command line arguments
   */
  public static void main(String[] args)
  {
    // turn bold fonts off in metal
    UIManager.put("swing.boldMetal", Boolean.FALSE);

    SwingUtilities.invokeLater(new Runnable()
    {
      public void run()
      {
        JFrame demoFrame = new TwoPartsComboBoxDemo();
        demoFrame.setTitle("Test GUI");
        demoFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        demoFrame.setSize(400, 100);
        demoFrame.setVisible(true);
      }
    });
  }
}

يمكنك استخدام العرف ListCellRenderer والتي من شأنها رسم العناصر الفاصلة بشكل مختلف.يرى مستندات وصغيرة درس تعليمي.

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