craftleft.gif (3002 bytes)QuickTable
Home | API | Tutorial | Download | Support | Contact topblack.gif (108 bytes)


QuickTable User Cp  |  Register  |  Members  |  Search  |  Help
    |- QuickTable Discussion Forums > CellEditor/Renderer Post New Topic   Post A Reply
Want to add a JPanel in each cell of a column printer friendly version
next newest post | next oldest post
Author Messages
jamen
Corporal

Gender: Unspecified
Location:
Registered: Sep 2007
Status: Offline
Posts: 22

Click here to see the profile for jamen Send email to jamen Send private message to jamen Find more posts by jamen Edit or delete this message Reply w/Quote
Posted Tuesday, October 16, 2007 @ 10:21:12  

I want to add a JPanel that paints itself as a simple line graph as one of the columns in QuickTable. I'm using a database and getting aggregate information for each row. For example: 'group 1' is row 1 of the table and column 1 is the max value from all the data that makes up 'group 1', column 2 is min data... etc. finally the last column is the line graph that plots (small, I admit) all the data from 'group 1'. I tried adding this JPanel several ways but the best I could get was the cell to display the panels .toString() method. I don't need an editor for the cell. I don't think I can figure out how to use DBTableCellRenderer given the documentation, plus I get the distinct feeling you don't want people to use it anyway. Any suggestions? I thought I saw that the source for QuickTable was available but can't seem to find that now. Also, just as a suggestion, meaningful variable names in the interfaces like (int row, int col) instead of (int _int1, int _int2) would make it much easier to use.

Thanks for continuing to support your product.

Admin
Board Owner

Gender: Unspecified
Location:
Registered: Jul 2003
Status: Offline
Posts: 9

Click here to see the profile for Admin Send email to Admin Send private message to Admin Find more posts by Admin Edit or delete this message Reply w/Quote
Posted Tuesday, October 16, 2007 @ 13:00:19  

what you really need is a User cell Renderer. Please create a Renderer using the class CellComponent and assign it to your column using Column.setUserCellRenderer(CellComponent)

The api documentation of cellComponent has more information about this. You can also checkout CustomerOrderDemo.java sample. You can also search forum for CellComponent

QuickTable code is written using (int row, int col), but sometimes IDEs will create source code from class files, during those times this information might get lost.

jamen
Corporal

Gender: Unspecified
Location:
Registered: Sep 2007
Status: Offline
Posts: 22

Click here to see the profile for jamen Send email to jamen Send private message to jamen Find more posts by jamen Edit or delete this message Reply w/Quote
Posted Tuesday, October 16, 2007 @ 20:54:12  

Ok, that pretty much worked. I had tried to use CellEditor and failed but all I had to do was change the class name and I was pretty much good to go. I do have a problem with the quick table refreshes though. If I don't put the panels back in after every refresh they don't paint. (They act like they are there but don't paint). Also the MonitorCellProperty doesn't seem to stick after refreshes either.

Here is my reload code that I use for intial table load and also whenever something changes.

Thanks again.

public void reload() {
int selectedRow = qTable.getSelectedRow();

try {
qTable.filter(null);
qTable.refresh();
}
catch (SQLException ex) {
Notify.showErrorDialog(ex.toString());
}

// try to reset the row selection to the same one before the refresh
qTable.selectCell(selectedRow, 0);

qTable.setCellPropertiesModel(new MonitorCellProperty(this));

loadCharts();

}

private void loadCharts() {
if (mcArray.size() > 0) {

double maxY = dvmActions.getMonitorDataMaxY();
double minY = dvmActions.getMonitorDataMinY();

for (int row = 0; row < qTable.getRowCount(); row++) {
MonitorChart mc = mcArray.get(row);
mc.setYLimits(maxY, minY);
qTable.setValueAt(mcArray.get(row), row, CHART_COLUMN - 1);
}
}
}

Admin
Board Owner

Gender: Unspecified
Location:
Registered: Jul 2003
Status: Offline
Posts: 9

Click here to see the profile for Admin Send email to Admin Send private message to Admin Find more posts by Admin Edit or delete this message Reply w/Quote
Posted Tuesday, October 16, 2007 @ 21:28:18  

I don't really understand your code.

what is your CellComponent class?

if you refresh, you need to reassign the cell component to the column using column.setUserCellRenderer

jamen
Corporal

Gender: Unspecified
Location:
Registered: Sep 2007
Status: Offline
Posts: 22

Click here to see the profile for jamen Send email to jamen Send private message to jamen Find more posts by jamen Edit or delete this message Reply w/Quote
Posted Tuesday, October 16, 2007 @ 21:49:41  

I didn't put the CellCOmponent class in because I didn't think it was relevent. I was / am reloading the contents of the cell with qTable.setValueAt(mcArray.get(row), row, CHART_COLUMN - 1); where mcArray is an array of the panels. Kind of convoluted I admit. I'll try reassigning the CellComponent tomarrow.

>>if you refresh, you need to reassign the cell component to the column using column.setUserCellRenderer

I assume that holds true for setCellPropertiesModel() as well?

Here is the CellComponent class below. The MonitorChart class is a simple JPanel extension that paints itself.

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

import quick.dbtable.*;
import java.awt.BorderLayout;

public class ChartCell
extends JPanel implements CellComponent {

MonitorChart mc = null;

BorderLayout borderLayout_cell = new BorderLayout();

public ChartCell() {
this.setLayout(borderLayout_cell);
}

/**
*
* @param aListener ActionListener
*/
public void addActionListener(ActionListener aListener) {
// we won't do anything since clicking on the chart does nothing for us
}

/**
*
* @param o Object
*/
public void setValue(Object o) {

if (o instanceof MonitorChart) {
mc = (MonitorChart) o;
add(mc, BorderLayout.CENTER);
}

}

/**
*
* @return Object
*/
public Object getValue() {
return mc;
}

/**
*
* @return JComponent
*/
public JComponent getComponent() {
return this;
}

}

Quote:
[/QUOTE] [QUOTE]
Quote:
[/QUOTE] [QUOTE]
[QUOTE][/QUOTE]
Admin
Board Owner

Gender: Unspecified
Location:
Registered: Jul 2003
Status: Offline
Posts: 9

Click here to see the profile for Admin Send email to Admin Send private message to Admin Find more posts by Admin Edit or delete this message Reply w/Quote
Posted Wednesday, October 17, 2007 @ 10:07:28  

It looks like MonitorChart is a UI object. Are you using an UIObject as a cellvalue? which is not correct. The cell value should be just chart data, the MonitorChart UI should be CellComponent.

You should really implement MonitorChart as "class MonitorChart implements CellComponent" and use that as your renderer.

jamen
Corporal

Gender: Unspecified
Location:
Registered: Sep 2007
Status: Offline
Posts: 22

Click here to see the profile for jamen Send email to jamen Send private message to jamen Find more posts by jamen Edit or delete this message Reply w/Quote
Posted Wednesday, October 17, 2007 @ 11:34:38  

Ok, I think I'm more confused now than before. I made MonitorChart implement CellComponent:

public class MonitorChart extends JPanel implements CellComponent

Made MonitorChart the CellRenderer for the newly created column for it:

chartColumn.setUserCellRenderer(new MonitorChart(minY, maxY));

(MonitorChar gets instantiated once [ I sort of thought it would be once for each cell in the row] )

I load the data to plot using QuickTables setValueAt method for each row in the column:

for (int row = 0; row < qTable.getRowCount(); row++) {
qTable.setValueAt(dataArray.get(row), row, CHART_COLUMN - 1); // I created the new column with a '1' based nubmer system but have to reference it here with a '0' based number system
}

and now I expect that the Object that is passed to MonitorChart in the [CellCOmponent].setValue(Object o) method will be the same object that I set using the qTable.setValueAt() method above. What I do get is an object of the same Type as I set but now its contents are empty. I also expect that the graphics object in:
public void paint(Graphics g)
of MonitorChart will cover the part of the canvas that is for the cell at that row,column. However, its not, since when I force it to draw something its drawing it at the (0,0) point of the quickTable object.

Here is the entire MonitorChart class now (sorry, its gotten messy with all the changes)

public class MonitorChart
extends JPanel implements CellComponent {

double xMin = +9999999999999.9;
double yMin = +9999999999999.9;
double xMax = -9999999999999.9;
double yMax = -9999999999999.9;

ArrayList<DoublePoint> xyList = new ArrayList<DoublePoint> ();

int xyListSize = 0;

BorderLayout borderLayout_cell = new BorderLayout();

public MonitorChart(double yMin, double yMax) {

this.yMax = yMax;
this.yMin = yMin;

this.setLayout(borderLayout_cell);
this.setPreferredSize(new Dimension(40, 20));
this.setMinimumSize(new Dimension(30, 15));

}

/**
*
*/
private void computeMax() {

for (int i = 0; i < xyListSize; i++) {

if (xyList.get(i).getY() > yMax) {
yMax = xyList.get(i).getY();
}
if (xyList.get(i).getY() < yMin) {
yMin = xyList.get(i).getY();
}
if (xyList.get(i).getX() > xMax) {
xMax = xyList.get(i).getX();
}
if (xyList.get(i).getX() < xMin) {
xMin = xyList.get(i).getX();
}

}

}

/**
*
* @param aListener ActionListener
*/
public void addActionListener(ActionListener aListener) {
// we won't do anything since clicking on the chart does nothing for us
}

/**
*
* @param o Object
*/
public void setValue(Object o) {

if (o instanceof ArrayList) {
this.xyList = xyList;
xyListSize = xyList.size();
System.out.println("xyListSize upon setValue(Object o) " + xyListSize);
computeMax();
}

}

/**
*
* @return Object
*/
public Object getValue() {
return xyList;
}

/**
*
* @return JComponent
*/
public JComponent getComponent() {
return this;
}

/**
*
* @param g Graphics
*/
public void paint(Graphics g) {

if (xyList.size() < 2) {
System.out.println("No data in MonitorChart to plot");
return;
}

Graphics2D g2 = (Graphics2D) g;

// now paint the chart in the g2d object

double xScale = this.getWidth() / (xMax - xMin);
double yScale = this.getHeight() / (yMax - yMin);

g2.clearRect(0, 0, this.getWidth(), this.getHeight());

g2.setPaint(Color.red);

for (int i = 1; i < xyListSize; i++) {
// draw the line from xyList(i-1) to xyList(i)
g2.draw(new Line2D.Double(xyList.get(i - 1).getX() * xScale,
xyList.get(i - 1).getY() * yScale,
xyList.get(i).getX() * xScale,
xyList.get(i).getY() * yScale));
}

}

public String toString() {
return "MonitorChart class " + yMax + " " + yMin;
// return "";
}

}

jamen
Corporal

Gender: Unspecified
Location:
Registered: Sep 2007
Status: Offline
Posts: 22

Click here to see the profile for jamen Send email to jamen Send private message to jamen Find more posts by jamen Edit or delete this message Reply w/Quote
Posted Wednesday, October 17, 2007 @ 13:34:36  

oops. pesky cut and paste error.

if (o instanceof ArrayList) {
this.xyList = xyList;
this.xyList = (ArrayList)o;
xyListSize = xyList.size();
System.out.println("xyListSize upon setValue(Object o) " + xyListSize);
computeMax();
}

Now it seems to work pretty much as I expected. I have a pesky .toString() result when I click on the panel but I think I can figure out how to get rid of it.

jamen
Corporal

Gender: Unspecified
Location:
Registered: Sep 2007
Status: Offline
Posts: 22

Click here to see the profile for jamen Send email to jamen Send private message to jamen Find more posts by jamen Edit or delete this message Reply w/Quote
Posted Wednesday, October 17, 2007 @ 17:29:29  

One last issue (here at least). Everything works as expected now except after a column sort the panels don't stay in their rows. I would have assumed that the public void setValue(Object o) method would re-issue the data for that cell (whatever format it should be) so the CellRenderer can render it. It looks to me like after a column sort (click on header) that whatever the data for the last cell drawn is used to redraw all all the panels. In other words I have nRows exact copies of each cell in that row now. How does the cell renderer get data after a sort event?
jamen
Corporal

Gender: Unspecified
Location:
Registered: Sep 2007
Status: Offline
Posts: 22

Click here to see the profile for jamen Send email to jamen Send private message to jamen Find more posts by jamen Edit or delete this message Reply w/Quote
Posted Thursday, October 18, 2007 @ 10:41:55  

Sorting seems to be done by an 'ORDER BY' clause in the sql. Since my added column has a graphic in it the sql doesn't know how to include it in the order. I got it work (sort of) by clicking certain columns in a certain order but the easiest fix was to disable sorting altogether on that table since it really isn't needed. qTable.setSortEnabled(false);

From the theory of 'if its there it should work, if its not there it works already'

Post New Topic   Post A Reply Jump to:
Contact Us | QuickTable - A Java DBGrid | Privacy Policy All times are GMT -5 Hours.
Welcome to QuickTable Forums, Guest!  
Login
Username :
Password :
In order to fully utilize the abilities of this board, you are required to register as a member. Registration is free, and allows you to do lots of things including turning on or off certain features of this board. Register now!
Powered by CuteCast v2.0 BETA 2
Copyright © 2001-2003 ArtsCore Studios