2013-10-11 15 views
7

Hücrelerde bir ızgara çizip çizme (bir şeyleri kolayca doldurmak için). Genel olarak, sadece bazı panel boyutlarında çalışıyorum. Hücrenin, yerleştirilmesi gereken yere göre yaklaşık 1 piksel uzakta olması (çizginin üst üste binmesi). TBH Ben muhtemelen cevabı kendim bulmak için yeterince hesaplama yapmadım, bu yüzden benim için özür dilerim, gerçekten bu "hata" ya nasıl yaklaşacağından emin değilim.Hücre büyüklüklerini hesaplayın ve çizin (aralarında çizgilerle).

Neyse, işte kod: Eğer çalıştırırsanız

public class Gui extends JFrame { 

public static void main(String[] args) { 
    new Gui().setVisible(true); 
} 

public Gui() { 
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
    add(new JPanel() { 
     public static final int SIZE = 3; 
     /** Line thickness ratio to a block */ 
     public static final float LINE_THICKNESS = 0.1f; 

     /** @return the width of a block. */ 
     protected final int getBlockWidth() { 
      return getWidth()/SIZE; 
     } 

     /** @return the height of a block. */ 
     protected final int getBlockHeight() { 
      return getHeight()/SIZE; 
     } 

     /** @return the width of a cell. */ 
     protected final int getCellWidth() { 
      return (int) Math.ceil(getBlockWidth()*(1-LINE_THICKNESS)); 
     } 

     /** @return the height of a cell. */ 
     protected final int getCellHeight() { 
      return (int) Math.ceil(getBlockHeight()*(1-LINE_THICKNESS)); 
     } 

     @Override 
     public void paintComponent(Graphics g) { 
      g.setColor(new Color(0, 0, 255, 100)); 
      int lineWidth = (int) (LINE_THICKNESS * getBlockWidth()); 
      int lineHeight = (int) (LINE_THICKNESS * getBlockHeight()); 
      for(int i = 0; i <= SIZE; i++) { 
       g.fillRect(i * getBlockWidth() - lineWidth/2, 0, lineWidth, getHeight()); 
       g.fillRect(0, i * getBlockHeight() - lineHeight/2, getWidth(), lineHeight); 
      } 
      g.setColor(new Color(255, 0, 0, 100)); 
      for(int i = 0; i < SIZE; i++) { 
       for(int j = 0; j < SIZE; j++) { 
        int x = j * getBlockWidth() + lineWidth/2; 
        int y = i * getBlockHeight() + lineHeight/2; 
        Graphics temp = g.create(x, y, getCellWidth(), getCellHeight()); 
        drawCell(temp, i, j); 
       } 
      } 
     } 

     private void drawCell(Graphics g, int i, int j) { 
      g.fillRect(0, 0, getCellWidth(), getCellHeight()); 
     } 
    }); 
    setLocation(new Point(500, 200)); 
    setSize(new Dimension(600, 600)); 
} 
} 

muhtemelen ne demek istediğimi göreceksiniz. Kelimelerde iyi bir açıklama düşünemiyorum. İlk başta, çizginin yanında çizmek istediğimden + 1'e x ve y eklemem gerektiğini düşündüm ama bu (açıkçası) problemi diğer tarafa kaydırıyor.

Bunu daha büyük bir SIZE ile çalıştırmak (30 gibi) bana kenarlara açık alan veren başka bir hata verir. Biliyorum (ya da varsayalım) çünkü tamsayı kullanıyorum ve bir anlaşmadan çok büyük değil. Ama daha iyi bir yaklaşım için ipuçları (genel olarak) her zaman beklerim.

cevap

4

Bunu düzeltmenin çeşitli yolları vardır. Sana kod vermeyeceğim, çünkü (sorunuzu nasıl sorduğuna göre), kendi başlarına sorunları düşünmek ve çözmek isteyenlerden biri olursunuz.

Her şeyden önce: önce tüm paneli arka plana çizin ve ardından çizgilerin çizin. Zaman çizgileri olmayacak ve çizim biraz daha hızlı olacak. İkinci yol: Çizim sırasının önemi önemlidir. Önce arkaplanı güvenli bir şekilde çizebilirsiniz (örtüşüyor olsa bile) ve daha sonra sınırların üzerine yazabilirsiniz. Üçüncü yöntem: Mürekkepleri kullanmayın. Şamandıralar veya çiftler kullanın. Bütün belalarınız gidecektir.

Dördüncü yol: kalanını hesaplayın. Çizimlerin ne zaman çizildiğini ve ne zaman yapıldığını tahmin edebilirsiniz. Tahmin et ve uygun şekilde çiz.

0

Merhaba Ben de aynı problemi yaşadım ama uyguladığım çözüm, çok satırlı metin çizmek için Java Öğreticisi'nden elde edilen örneklerden ilham alıyor ve metin API'lerini kullanarak hücrede bulunan metni çiziyor. İyi bir SSCCE.org ve net, anlaşılır soru için

import java.awt.Component; 
import java.awt.Font; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.font.FontRenderContext; 
import java.awt.font.LineBreakMeasurer; 
import java.awt.font.TextLayout; 
import java.text.AttributedCharacterIterator; 
import java.text.AttributedString; 
import java.text.BreakIterator; 

import javax.swing.JTable; 
import javax.swing.table.DefaultTableCellRenderer; 
import javax.swing.table.TableCellRenderer; 


public class MultilineTableCell 
    implements TableCellRenderer { 
    class CellArea extends DefaultTableCellRenderer { 
     /** 
     * 
     */ 
     private static final long serialVersionUID = 1L; 
     private String text; 
     protected int rowIndex; 
     protected int columnIndex; 
     protected JTable table; 
     protected Font font; 
     private int paragraphStart,paragraphEnd; 
     private LineBreakMeasurer lineMeasurer; 

     public CellArea(String s, JTable tab, int row, int column,boolean isSelected) { 
      text = s; 
      rowIndex = row; 
      columnIndex = column; 
      table = tab; 
      font = table.getFont(); 
      if (isSelected) { 
       setForeground(table.getSelectionForeground()); 
       setBackground(table.getSelectionBackground()); 
      } 
     } 
     public void paintComponent(Graphics gr) { 
      super.paintComponent(gr); 
      if (text != null && !text.isEmpty()) { 
       Graphics2D g = (Graphics2D) gr; 
       if (lineMeasurer == null) { 
        AttributedCharacterIterator paragraph = new AttributedString(text).getIterator(); 
        paragraphStart = paragraph.getBeginIndex(); 
        paragraphEnd = paragraph.getEndIndex(); 
        FontRenderContext frc = g.getFontRenderContext(); 
        lineMeasurer = new LineBreakMeasurer(paragraph,BreakIterator.getWordInstance(), frc); 
       } 
       float breakWidth = (float)table.getColumnModel().getColumn(columnIndex).getWidth(); 
       float drawPosY = 0; 
       // Set position to the index of the first character in the paragraph. 
       lineMeasurer.setPosition(paragraphStart); 
       // Get lines until the entire paragraph has been displayed. 
       while (lineMeasurer.getPosition() < paragraphEnd) { 
        // Retrieve next layout. A cleverer program would also cache 
        // these layouts until the component is re-sized. 
        TextLayout layout = lineMeasurer.nextLayout(breakWidth); 
        // Compute pen x position. If the paragraph is right-to-left we 
        // will align the TextLayouts to the right edge of the panel. 
        // Note: this won't occur for the English text in this sample. 
        // Note: drawPosX is always where the LEFT of the text is placed. 
        float drawPosX = layout.isLeftToRight() 
         ? 0 : breakWidth - layout.getAdvance(); 
        // Move y-coordinate by the ascent of the layout. 
        drawPosY += layout.getAscent(); 
        // Draw the TextLayout at (drawPosX, drawPosY). 
        layout.draw(g, drawPosX, drawPosY); 
        // Move y-coordinate in preparation for next layout. 
        drawPosY += layout.getDescent() + layout.getLeading(); 
       } 
       table.setRowHeight(rowIndex,(int) drawPosY); 
      } 
     } 
    } 
    public Component getTableCellRendererComponent(
      JTable table, Object value,boolean isSelected, boolean hasFocus, int row,int column 
     ) 
    { 
     CellArea area = new CellArea(value.toString(),table,row,column,isSelected); 
     return area; 
    } 
} 
It resizes row heigth too but it does it well only when this renderer is used for a single column. 

And this is the way I used to invoke it for render my table. 

final int wordWrapColumnIndex = ...; 
myTable = new JTable() {  
    public TableCellRenderer getCellRenderer(int row, int column) { 
     if (column == wordWrapColumnIndex) { 
      return wordWrapRenderer; 
     } 
     else { 
      return super.getCellRenderer(row, column); 
     } 
    } 
};