I have a JTable with a number of columns. I want a particular column to resize. What I was hoping was by using setPreferredWidth, the column would resize to that size, or the size of the contents such that no truncation occurred and let the rest of the columns take the remaining space, but instead, all of the columns, including the one I resized, equally split all of the space of the table; as if setPreferredWidth did nothing at all. In effect, I want to be able to set the width of a column and have it shrink to that size without truncating content (have I stressed that too much yet?) in such a way that all columns that have not been resized fill the remaining space. Using setMaxWidth truncates content (did I mention I didn't like that?) How do I resize/shrink a column without it truncating and without it doing absolutely nothing? Here is the offending code:
for (int i = 0, x = 0; i < table.getColumnModel().getColumnCount(); i++)
if ((x = model.getColumnWidth(i)) > -1)
table.getColumnModel().getColumn(i).setPreferredWidth(x);
The table is in a JPanel (MyListPanel - BorderLayout) which is in another JPanel (GridBagLayout) added with:
new GridBagConstraints(0, 3, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(2, 0, 0, 2), 0, 0))
EDIT: This is the constructor for my subclass of JPanel:
public MyListPanel(boolean showHeader, String title, ColData...columns) {
super(new BorderLayout());
model = new MyListTableModel(columns);
table = new JTable(model);
table.addFocusListener(this);
add(table);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
setTitle(title);
if (showHeader)
add(table.getTableHeader(), BorderLayout.NORTH);
for (int i = 0, x = 0; i < table.getColumnModel().getColumnCount(); i++)
if ((x = model.getColumnWidth(i)) > -1)
table.getColumnModel().getColumn(i).setPreferredWidth(x);
setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
}
And MyListTableModel.ColData:
public static class ColData {
private int index;
private String title;
private int width;
public ColData(int _index, String _title, int _width) { index = _index; title = _title; width = _width; }
}
Include :
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
I had a similar problem despite trying the two other answers here. In my case, some times the width would get set correctly while other times, it would not. I found the problem was caused because I was trying to set the column widths immediately after changing my table model. I found setting the column widths inside of SwingUtilities.invokeLater() did the trick. I.E.
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
int width = 100;
for (int column = 1; column < table.getColumnCount(); column++) {
columnModel.getColumn(column).setPreferredWidth(width);
}
}
}
I know this is a bit late so is mostly for future readers, but I had the same problem and solved it by setting both the column's preferred width and maximum width to the same value.
I had the same issue and reading #Jay Askren answer, the opposite worked for me. I had to set the width in the method where the table was being created.
public class Example{
//..stuff
private JTable myTable;
public Example{
//..stuff
myTable = AnotherClass.getTable();
myTable .getColumnModel().getColumn(0).setPreferredWidth(100);//not here
}
}
public class AnotherClass{
public static JTable getTable(){
JTable table= new JTable();
table.setModel(anyModel);
table.getColumnModel().getColumn(0).setPreferredWidth(100);//Here!
return table
}
}
Set all three of setMinWidth, setMaxWidth and setPreferredWidth, where minimum_width <= preferred_width <= maximum_width.
int[] minColSizes = { 15, 55, 75, 50, 50, 50 };
int[] preferredColSizes = { 25, 75, 125, 100, 100, 100 };
int[] maxSizes = { 50, 100, 200, 200, 200, 200 };
for ( int index = 0; index < preferredColSizes.length; index++ )
{
myTable.getColumnModel().getColumn(index).setMinWidth ( minColSizes[index] );
myTable.getColumnModel().getColumn(index).setMaxWidth ( preferredColSizes[index] + 100 );
myTable.getColumnModel().getColumn(index).setPreferredWidth ( maxSizes[index] );
}
Related
In my report generation java application with iText 7, I need to get data from a large data tables which may extend to several pages.
My code segments to generate the table.
Table table = new Table(new float[] {0.4f, 1f, 1f, 1f, 1.3f, 1f, 1.3f, 0.6f,0.6f,1.2f}, true)
.setWidth(UnitValue.createPercentValue(100))
.setMarginTop(tblTopMargin)
.setMarginBottom(0);
int count = 0;
while (!dataList.empty()) {
String[] dataRow = dataList.poll();
createDataRow(dataRow, table);
count++;
if(count % 10 == 0) {
table.flush();
}
}
implementation of createDataRaw method is mentioned below,
private void createDataRow(String[] a, Table table) {
for (String s : a) {
Paragraph content = new Paragraph(s)
.setFontSize(7)
.setFixedLeading(9)
.setFontColor(new DeviceCmyk(0, 0, 0, 100));
Cell cell = new Cell()
.setBorder(new SolidBorder(ColorConstants.BLACK, 0.5f))
.setPaddingLeft(2)
.setPaddingTop(0)
.setPaddingBottom(0)
.setHorizontalAlignment(HorizontalAlignment.LEFT)
.setVerticalAlignment(VerticalAlignment.MIDDLE)
.add(content);
table.addCell(cell);
}
}
with the given code table generated with all the data. But when there is a page break between tables then the bottom line of the table is not showing except for the last table bottom.
screenshots are attached here to get a more clear idea.
Can someone help me to solve this issue?
The following code produces the desired result for me for the latest 7.1.16 version of iText:
Table table = new Table(new float[] {0.4f, 1f, 1f}, true)
.setWidth(UnitValue.createPercentValue(100))
.setMarginBottom(0);
document.add(table);
int count = 0;
for (int i = 0; i < 300; i++) {
String[] dataRow = new String[] {"1\n2\n3\n4\n5\n6\n7\n8\n9\n10", "2\n3\nsf\n43", "3\nr\nsdfsd\n43"};
createDataRow(dataRow, table);
count++;
if (count % 10 == 0) {
table.flush();
}
}
table.complete();
document.close();
private void createDataRow(String[] a, Table table) {
for (String s : a) {
Paragraph content = new Paragraph(s)
.setFontSize(7)
.setFixedLeading(9)
.setFontColor(new DeviceCmyk(0, 0, 0, 100));
Cell cell = new Cell()
.setBorder(new SolidBorder(ColorConstants.BLACK, 0.5f))
.setPaddingLeft(2)
.setPaddingTop(0)
.setPaddingBottom(0)
.setHorizontalAlignment(HorizontalAlignment.LEFT)
.setVerticalAlignment(VerticalAlignment.MIDDLE)
.add(content);
table.addCell(cell);
}
}
Visual result (end of first page):
I've been doing a CrossWord puzzle in java for a project. However I haven't been able to fix one problem I'm having with drawing the CrossWord into a JPanel
The program takes the data from a 2D array of chars and generates a grid of a custom type of JLabels with it. This is the code:
public void update(Observable o, Object o1) {
if(model.getMatrix() != null){
configurePanel(model.getRows(), model.getCols());
this.add(panel);
this.pack();
this.revalidate();
this.repaint();
}
}
private void configurePanel(int w, int h) {
if (panel!=null){
this.remove(panel);
}
panel = new JPanel();
panel.setBounds(40, 40, w*50, h*50);
panel.setLayout(new GridLayout(w, h));
labels = createLabels(model.getMatrix());
for (int i = 0; i < w; i++){
for(int j = 0; j < h; j++){
panel.add(labels[i][j]);
}
}
}
private CWlabel[][] createLabels(char[][] matrix) {
int w = matrix.length;
int h = matrix[0].length;
labels = new CWlabel[w][h];
for (int i = 0; i < w; i++){
for(int j = 0; j < h; j++){
char c = matrix[i][j];
labels[i][j] = new CWlabel();
labels[i][j].setBorder(BorderFactory.createLineBorder(Color.black));
labels[i][j].setOpaque(true);
if (c != ' '){
labels[i][j].setBackground(Color.white);
} else {
labels[i][j].setBackground(Color.black);
}
}
}
return labels;
}
My main problem is in configurePanel(), where the size of the panel are set proportional to the crossword dimensions, which should ensure every component inside it is perfectly square, however this is not the case as seen here
In the example shown the difference is subtle but still notizable. The strange part its that if I manually replace,
panel.setBounds(40, 40, w*50, h*50);
with,
panel.setBounds(40, 40, 400, 450);
the result appears to be proportional to the amount of rows and columns as shown here
By my count you have 9 rows and 8 columns so calling configurePanel like the following:
configurePanel(model.getRows(), model.getCols());
Is going to result in a width of 450 and a height of 400, but you want a width of 400 and a height of 450. Thus switch around the first and second parameters, like the following:
configurePanel(model.getCols(), model.getRows());
Note: You shouldn't use absolute positioning, it causes many formatting problems down the road (resizing components, adding components, etc.). You should instead use a layout manager with more customization like GridBagLayout or MigLayout.
I have the following Processing program:
//using Papplet instead of STDraw to visually represent my grid, created by Mahmed Ibrahim
import java.awt.Color;
import processing.core.*;
import processing.core.PApplet;
public class C4Grid extends PApplet {
PShape s;
PShape[][] circleSpaces;
boolean[][] circleSpacesFilled;
boolean[][] circleHasYelowPiece;
boolean[][] circleHasRedPiece;
final float SPACES_BETWEEN_ROWS = 110;
final float SPACES_BETWEEN_COLUMNS = 130;
public C4Grid(){}
public void setup() {
System.out.println("it got to here where it breaks");
size(1000, 1000, P2D);
// Making the shape of the grid using vertices
// so I'm manually drawing my polygon.
s = createShape();
s.beginShape();
s.fill(34, 56, 100);
s.tint(34, 56, 100);
s.stroke(0);
s.strokeWeight(5);
s.vertex(400, 400);
s.vertex(400, -440);
s.vertex(360, -440);
s.vertex(360, -400);
s.vertex(-360, -400);
s.vertex(-360, -440);
s.vertex(-400, -440);
s.vertex(-400, 420);
s.vertex(-420, 420);
s.vertex(-420, 440);
s.vertex(-360, 440);
s.vertex(-360, 420);
s.vertex(-380, 420);
s.vertex(-380, 400);
s.vertex(380, 400);
s.vertex(380, 420);
s.vertex(360, 420);
s.vertex(360, 440);
s.vertex(420, 440);
s.vertex(420, 420);
s.vertex(400, 420);
s.vertex(400, 420);
s.vertex(400, -440);
s.vertex(400, 400);
s.endShape();
System.out.println("it got to here where it breaks");
// using a 2D array to create a grid of circles
// which will represent the spaces on the grid
circleHasYelowPiece = new boolean[7][6];
circleHasRedPiece = new boolean[7][6];
circleSpacesFilled = new boolean[7][6];
circleSpaces = new PShape[7][6];
for (int row = 0; row < 7; row++) {
for (int column = 0; column < 6; column++) {
circleSpaces[row][column] = createShape(ELLIPSE, -380 + (row) * SPACES_BETWEEN_ROWS,
-370 + (column) * SPACES_BETWEEN_COLUMNS, 100, 100);
circleSpaces[row][column].disableStyle();
stroke(0);
strokeWeight(5);
circleSpacesFilled[row][column] = false;
circleHasRedPiece[row][column] = false;
circleHasYelowPiece[row][column] = false;
}
}
}
public void draw() {
translate(width / 2, height / 2);
shape(s);
for (int row = 0; row < 7; row++) {
for (int column = 0; column < 6; column++) {
shape(circleSpaces[row][column]);
}
}
}
public boolean piecePlaced(int column, Color pieceColor) {
column = column - 1; // the choice are form 1-7 but in an array its 0-6;
boolean moveDone = false;
int i = 5;
Color red = new Color(255, 0, 0);
while (i >= 0) {
if (circleSpacesFilled[column][i] == false) {
circleSpacesFilled[column][i] = true;
if (pieceColor.equals(red)) {
circleHasRedPiece[column][i] = true;
circleSpaces[column][i].fill(255, 0, 0);
circleSpaces[column][i].tint(255, 0, 0);
} else {
circleHasYelowPiece[column][i] = true;
circleSpaces[column][i].fill(255, 255, 0);
circleSpaces[column][i].tint(255, 255, 0);
}
return true;
}
}
return false;
}
}
When I run it, I get this NullPointerException. Notice that the exception is coming from within Processing's libraries - it's not directly caused by my own code!
The 3 lines that are suspect are:
currentGame = new C4Game(player1Is,player2Is,player1Color,player2Color);
theGrid = new C4Grid(); theGrid.setup();
s= createShape(); near the top of setup()
currentGame, theGrid, and s are all non-null (I've checked countless times).
Even when I test each line in isolation, I get an error in anything that related to the PShape class. I got rid of every PShape object and it worked, but is there a way to fix it so I can use PShape as part of my code?
When I run your code, I don't get a NullPointerException. I get an error that says this:
When not using the PDE, size() can only be used inside settings().
Remove the size() method from setup(), and add the following:
public void settings() {
size(1000, 1000, "processing.opengl.PGraphics2D");
}
And the error says it all. When you're using Processing as a library, you can't call the size() function from the setup() function. Call it from the settings() function instead.
If I make that change, your code runs fine:
I am working on a program that takes an array of doubles and displays them all in one line on a horizontal bar graph. Right now it works except for the coloring. I have an indeterminate amount of rows so the data is added to the graph like this:
public CategoryDataset createDataset() {
DefaultCategoryDataset bardataset1 = new DefaultCategoryDataset();
for (int i = 0; i < nanoArray.length; i++) {
bardataset1.addValue(nanoArray[i], "Packet" + i, "Class A");
bardataset1.addValue(startgap, "Packet Gap" + i, "Class A");
}
}
This stacks the data properly but because there are around 300 different rowKeys it assigns 300 different colors. I attached this picture to show you what it looks like:
http://i.imgur.com/hg33P.png
As you can see this makes the data completely unreadable. What I want is to see bars of alternating colors of red then blue.
Edit: I have found the answer; I used jcern's method. I also wrote a for loop that iterates through the length of my double array and assigns a color based on whether it is even or odd.
for (int i = 0; i < packetCount; i++) {
setSeriesToolTipGenerator(i, new StandardCategoryToolTipGenerator());
if (i % 2 == 0) {
setSeriesPaint(i, new Color(255, 0, 0));
} else {
setSeriesPaint(i, new Color(0, 0, 0));
}
}
You need to create a new renderer and specify that to the plot.
First, you'll create a render that has the two colors you want:
CategoryItemRenderer renderer = new StackedBarRenderer {
private Paint[] colors = new Paint[] {
new Color(255, 0, 0),
new Color(0, 0, 255)
}
public Paint getSeriesPaint(int series) {
return colors[(series % 2)];
}
};
Then, grab the plot and specify which render you want to use:
if(chart.getPlot() instanceof CategoryPlot){
chart.getCategoryPlot().setRenderer(renderer);
}
Hopefully, that should get you where you want to be.
How can I remove the border around the cells in a swing JTable completely, so the cells have no gaps between them?
Here is what I have tried:
table.setShowGrid(false);
table.setShowVerticalLines(false);
table.setShowHorizontalLines(false);
and writing a cell renderer and using:
setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
for each individual cell.
But the result is the lines between the cells are removed but a 1 pixel gap is left between them.
and writing a cell renderer and using:
everything depends what Renderer returns but without Renderer works for me
setIntercellSpacing()
setShowGrid()
import java.awt.*;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
public class TableExample {
public TableExample() {
Object[][] data1 = new Object[50][5];
for (int i = 0; i < data1.length; i++) {
data1[i][0] = "Company # " + (i + 1);
for (int j = 1; j < data1[i].length; j++) {
data1[i][j] = "" + (i + 1) + ", " + j;
}
}
String[] headers = {"Col 1", "Col 2", "Col 3", "Col 4", "Col 5"};
DefaultTableModel model1 = new DefaultTableModel(data1, headers);
final JTable jTable3 = new TableBackroundPaint0(data1, headers);
//final JTable jTable3 = new JTable(data1, headers);
jTable3.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
jTable3.setModel(model1);
final JScrollPane sp3 = new JScrollPane();
sp3.setViewportView(jTable3);
jTable3.setIntercellSpacing(new Dimension(0, 0));
jTable3.setShowGrid(false);
//jTable3.setPreferredScrollableViewportSize(jTable3.getPreferredSize());
JFrame frame = new JFrame("tableSelection");
frame.add(sp3);
frame.setSize(new Dimension(600, 200));
//frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
TableExample te = new TableExample();
}
});
}
}
class TableBackroundPaint0 extends JTable {
private static final long serialVersionUID = 1L;
TableBackroundPaint0(Object[][] data, Object[] head) {
super(data, head);
setOpaque(false);
((JComponent) getDefaultRenderer(Object.class)).setOpaque(false);
}
#Override
public void paintComponent(Graphics g) {
Color background = new Color(168, 210, 241);
Color controlColor = new Color(230, 240, 230);
int width = getWidth();
int height = getHeight();
Graphics2D g2 = (Graphics2D) g;
Paint oldPaint = g2.getPaint();
g2.setPaint(new GradientPaint(0, 0, background, width, 0, controlColor));
g2.fillRect(0, 0, width, height);
g2.setPaint(oldPaint);
for (int row : getSelectedRows()) {
Rectangle start = getCellRect(row, 0, true);
Rectangle end = getCellRect(row, getColumnCount() - 1, true);
g2.setPaint(new GradientPaint(start.x, 0, controlColor, (int) ((end.x + end.width - start.x) * 1.25), 0, Color.orange));
g2.fillRect(start.x, start.y, end.x + end.width - start.x, start.height);
}
super.paintComponent(g);
}
}
You can just set color of border to background color of cell. Also, please have a look at these examples,
http://www.java2s.com/Code/Java/Swing-Components/CellBorderTableExample.htm
http://www.esus.com/docs/GetQuestionPage.jsp?uid=1290
You can use these methods in JTable in order to remove the grid if your column models are not auto generating (without data binding).
setShowGrid(false);
setRowMargin(0);
setShowVerticalLines(false);
setShowHorizontalLines(false);
But If you created column models using data binding then you have trouble. That is even if you call these methods their is still paint white 1 pixel gap in each column margin.
You can remove that column margin by using custom DefaultTableColumnModel.
private class CustomDefaultTableColumnModel extends DefaultTableColumnModel{
#Override
public void setColumnMargin(int newMargin) {
//Always set ColumnMargin to zero.
//Because after the column data binding its internally set one as ColumnMargin.
//That course to paint white color grid.
//To stop we override the setColumnMargin and pass zero to ColumnMargin.
super.setColumnMargin(0);
}
}
Then you can add your custom table column model into your table.
setColumnModel(new CustomDefaultTableColumnModel());