2016-12-14 4 views
2

Я уже спросил здесь, поэтому, пожалуйста, прочитайте здесь. Этот вопрос частично решена. How can I add \t spacing in a String that belongs to a DefaultListModel which belongs to a JLIst?Как равномерно размещать строки в String.format, это DefaultListModel внутри JList?

Теперь у меня есть еще одна проблема:

Пожалуйста, смотрите на этом примере первый

// Declarations 
String string1 = "Eggs"; 
String string2 = "Whole Chicken"; 
int quantity1 = 100; 
int quantity2 = 25; 

// HTML and PRE tags are added before and after string 
StringBuilder builder1 = new Stringbuilder; 
builder.append("<html><pre>"); 
builder.append(String.format("%s \t %d", string1, quantity1)); 
builder.append("</pre></html>"); 

StringBuilder builder2 = new Stringbuilder; 
builder.append("<html><pre>"); 
builder.append(String.format("%s \t %d", string2, quantity2)); 
builder.append("</pre></html>"); 

// JList is defined, and the builder is added to the list. 
JList<String> list = new JList<String>(); 
list.addElement(builder1.toString()); 
list.addElement(builder2.toString()); 

Это, как он будет отображать все элементы

Eggs 100 
Whole Chicken 25 

Что бы я должно случиться так, что все переменные количества выровнены, а не разнесены d по предыдущей переменной. Любые идеи, как я мог это сделать?

Спасибо!

==========================

Еще одно предложение было бы, если это возможно, чтобы определить минимальную длину строки в a String.format()?

ответ

0

Как сказал @GhostCat, использование ширины в строке формата решит вашу проблему.

Для получения дополнительной информации, посмотрите на строку формата documentation.

Однако, что вы пытаетесь сделать, заставляет меня думать, что, возможно, вместо использования JList вы можете использовать JTable?

import javax.swing.*; 

public class ssce{ 
    public static void main(String... args){ 
     // Declarations 
     String string1 = "Eggs"; 
     String string2 = "Whole Chicken"; 
     int quantity1 = 100; 
     int quantity2 = 25; 

     JFrame f = new JFrame("prova"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 


     String[] col = {"Ingredient", "Quantity"}; 
     Object[][] data = { 
      {string1, new Integer(quantity1)}, 
      {string2, new Integer(quantity2)} 
     }; 
     JTable tb = new JTable(data, col); 
     f.add(tb); 
     f.setSize(300, 400); 
     f.setVisible(true); 
    } 
} 
+0

Пример, взятый непосредственно из учебника. С небольшим количеством дополнительной работы и созданием пользовательской «TableModel» вы можете делать гораздо больше. – bracco23

0

Вы можете просто использовать

%20s 

, например - что поставит 20 пробелов в форматированном вывод.

Итак, трюк в основном для первого сканирования всех строк в вашем списке, чтобы затем вычислить разумное число, которое вам нужно в вашем шаблоне форматирования. Другими словами: сначала вы хотите определить максимальную длину отображаемых строк; затем вычислить соответствующий отступ, например.

EDIT: Есть много различных способов повлиять на форматирование, посмотреть question или enter link description here или лучший, изучить javadoc, который определяет все шаблоны форматирования, которые существуют!

+0

Это работает так красиво! Еще одна вещь: можно ли выровнять строку1/string2 влево, а не вправо? –

+0

Добро пожаловать. A) см. Мои обновления B) в случае, если вы счастливы, подумайте о принятии моего ответа ... – GhostCat

0

наиболее простым решением является использование моноширинный шрифт и строку формата.

public class Main { 

    public static void main(String[] args) { 
    JFrame frame = new JFrame(); 
    frame.setSize(320, 100); 
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 

    Container contentPane = frame.getContentPane(); 

    DefaultListModel<String> defaultListModel = new DefaultListModel<>(); 
    defaultListModel.addElement(String.format("%-20s %d", "Eggs", 100)); 
    defaultListModel.addElement(String.format("%-20s %d", "Whole Chicken", 25)); 

    JList<String> jList = new JList<>(defaultListModel); 
    Font defaultListFont = jList.getFont(); 
    jList.setFont(new Font("monospaced", defaultListFont.getStyle(), defaultListFont.getSize())); 

    contentPane.add(jList); 
    frame.setLocationRelativeTo(null); 
    frame.setVisible(true); 
    } 
} 

, что приведет к

With monospaced font

Раствор без использования моноширинный шрифт

Если вы хотите, чтобы выровнять ширину столбцов в зависимости от ListModel я бы слушать ListModel изменения для вычисления самой длинной строки в модели и использования настраиваемого средства визуализации.

public static void main(String[] args) { 
    JFrame frame = new JFrame(); 
    frame.setSize(320, 150); 
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 

    Container contentPane = frame.getContentPane(); 

    DefaultListModel<String[]> defaultListModel = new DefaultListModel<>(); 
    defaultListModel.addElement(new String[]{"Eggs", "100"}); 
    defaultListModel.addElement(new String[]{"The longest Entry in the list", "12125"}); 
    defaultListModel.addElement(new String[]{"Whole Chicken", "25"}); 

    JList<String[]> jList = new JList<>(defaultListModel); 

    ListModelAwareColumnWidthProvider listModelAwareColumnWidthProvider = new ListModelAwareColumnWidthProvider(); 
    listModelAwareColumnWidthProvider.setListModel(defaultListModel); 

    ColumnCellRenderer columnCellRenderer = new ColumnCellRenderer(listModelAwareColumnWidthProvider); 
    jList.setCellRenderer(columnCellRenderer); 

    contentPane.add(jList); 
    frame.setLocationRelativeTo(null); 
    frame.setVisible(true); 
} 

и вы должны сделать что-то вроде этого

рендерер, который поддерживает столбцы

class ColumnCellRenderer implements ListCellRenderer<String[]> { 

    private ColumnWidthProvider columnWidthProvider; 

    public ColumnCellRenderer(ColumnWidthProvider columnWidthProvider) { 
    this.columnWidthProvider = columnWidthProvider; 
    } 


    @Override 
    public Component getListCellRendererComponent(JList<? extends String[]> list, String[] value, int index, boolean isSelected, boolean cellHasFocus) { 
    JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT)); 

    for (int i = 0; i < value.length; i++) { 
     String valueElement = value[i]; 

     JLabel label = new JLabel(valueElement); 

     align(label, i); 
     panel.add(label); 
    } 

    applyColors(list, panel, isSelected); 

    return panel; 
    } 

    private void applyColors(JList<?> list, JComponent component, boolean isSelected) { 
    if (isSelected) { 
     component.setForeground(list.getSelectionForeground()); 
     component.setBackground(list.getSelectionBackground()); 
    } else { 
     component.setForeground(list.getForeground()); 
     component.setBackground(list.getBackground()); 
    } 
    } 

    private void align(JComponent component, int columnIndex) { 
    Font font = component.getFont(); 
    FontMetrics fontMetrics = component.getFontMetrics(font); 
    int fontHeight = fontMetrics.getHeight(); 

    int columnWidth = columnWidthProvider.getColumnWidth(fontMetrics, columnIndex); 
    component.setPreferredSize(new Dimension(columnWidth, fontHeight)); 
    } 

} 

интерфейс для визуализатора для получения ширины столбца

interface ColumnWidthProvider { 
    public int getColumnWidth(FontMetrics fontMetrics, int columnIndex); 
} 

и реализация ColumnWidthProvider, которая наблюдает за ListModel Палатка изменения

class ListModelAwareColumnWidthProvider implements ColumnWidthProvider { 

    private class ListModelChangeAdapter implements ListDataListener { 
    @Override 
    public void intervalAdded(ListDataEvent e) { 
     initializeColumnWidths(); 
    } 

    @Override 
    public void intervalRemoved(ListDataEvent e) { 
     initializeColumnWidths(); 
    } 

    @Override 
    public void contentsChanged(ListDataEvent e) { 
     initializeColumnWidths(); 
    } 
    } 

    private int defaultColumnWidth = 100; 

    private ListModelChangeAdapter listModelChangeAdapter = new ListModelChangeAdapter(); 
    private ListModel<String[]> listModel; 
    private java.util.List<String> longestColumnStrings = new ArrayList<>(); 

    public void setListModel(ListModel<String[]> listModel) { 
    if (this.listModel != null) { 
     this.listModel.removeListDataListener(listModelChangeAdapter); 
    } 

    this.listModel = listModel; 
    initializeColumnWidths(); 

    if (this.listModel != null) { 
     this.listModel.addListDataListener(listModelChangeAdapter); 
    } 
    } 

    private void initializeColumnWidths() { 
    longestColumnStrings.clear(); 

    if (listModel != null) { 
     int size = listModel.getSize(); 
     for (int i = 0; i < size; i++) { 
     String[] elementAt = listModel.getElementAt(i); 

     for (int columnIndex = 0; columnIndex < elementAt.length; columnIndex++) { 
      String columnValue = elementAt[columnIndex]; 

      while (columnIndex >= longestColumnStrings.size()) { 
      longestColumnStrings.add(null); 
      } 

      String lastLongestColumnString = longestColumnStrings.get(columnIndex); 
      if (lastLongestColumnString == null) { 
      longestColumnStrings.set(columnIndex, columnValue); 
      } else if (columnValue.length() > lastLongestColumnString.length()) { 
      longestColumnStrings.set(columnIndex, columnValue); 
      } 
     } 
     } 
    } 
    } 

    public void setDefaultColumnWidth(int defaultColumnWidth) { 
    this.defaultColumnWidth = defaultColumnWidth; 
    } 

    @Override 
    public int getColumnWidth(FontMetrics fontMetrics, int columnIndex) { 
    if (columnIndex < longestColumnStrings.size()) { 
     String longestColumnString = longestColumnStrings.get(columnIndex); 
     return fontMetrics.stringWidth(longestColumnString); 
    } 
    return defaultColumnWidth; 
    } 
} 

, что приведет к

With renderer