In my application, I am reading a .xml file and writing the data in a JTable. Apart from the data for the table, the .xml file contains an attribute defining the background color of each row. My method for cell rendering looks something like this:
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int col) {
JComponent comp = new JLabel();
if (null != value) {
//reading the data and writing it in the comp
}
GenericTableModel model = (GenericTableModel) table.getModel();
GenericObject go = model.getRowObject(row);
Color test = new Color(255, 255, 255);
if (go.getValueByName("COLOR") == null){
}else{
test =(Color) go.getValueByName("COLOR");
}
comp.setBackground(test);
return comp;
}
The .xml file is initialized within the program. My problem is that I don't know how to define the color in the file so that the variable test will be able to save it as a color. I tried writing it as "Color.white", "white" and even "255, 255, 255" but i get a casting error when I try saving it in the variable.
Any ideas as to how could I define the color in the file?
I take it that GenericObject#getValueByName() returns a string, right? In that case you need to convert the string to something that can be used to create a Color instance. Assuming that the string is "R,G,B", then split the string on the comma, convert each component to an integer and create a color:
public static Color fromString(String rgb, Color deflt) {
String[] comp = rgb.split(",");
if (comp.length != 3)
return deflt;
int rc[] = new int[3];
for (int i = 0; i < 3; ++i) {
rc[i] = Integer.parseInt(comp[i].trim());
if (rc[i] < 0 || rc[i] > 255)
return deflt;
}
Color c = new Color(rc[0], rc[1], rc[2]);
return c;
}
The other alternative is to define the color field with color names matching the predefined static fields in Color (Color.BLACK, Color.RED, etc), and use reflection to get the correct field, but I leave that as an excercise.
As a followup to forty-two's answer, it really depends on how the color is supposed to be stored in the XML. It would also be possible to save the color's value as a single string (no commas), representing either the decimal or hex value of the color. (Hex is more human-readable for colors, e.g. "FFFF00" for Yellow instead of "16776960")
e.g. as decimal (and with no error checking, for the record, I like default values like forty-two used)
public static Color readColor(String decimalString) {
return new Color(Integer.parseInt(decimalString));
}
public String writeColor(Color color) {
return Integer.toString(color.getRGB());
}
e.g. as hex (you need avoidOverflows to handle colors with alpha values like F0123456)
public static Color readColor(String hexString) {
long avoidOverflows = Long.parseLong(hexString, 16);
return new Color((int)long);
}
public String writeColor(Color color) {
return Integer.toHexString(color.getRGB(), 16);
}
I've even seen the hex values preceded by a "#" to make them more HTML-like. So, it really depends on the spec for your XML.
Related
i have a problem, basically my program looks like this:
the thing is, it works, it is supposed to color the rows that have "N" in green, but the first time it loads the values, as you can see, the first row have bits of white, but for some reason if i click the list it fixes the issue, i need the rows to be colored properly without the user needing to click on the list to fix the issue, this is my Render code:
public class Render extends JTable {
#Override
public Component prepareRenderer(TableCellRenderer renderer, int rowIndex,
int columnIndex){
Component componente = super.prepareRenderer(renderer, rowIndex, columnIndex);
String val = getValueAt(rowIndex, columnIndex).toString();
if(val.equals("N")){
componente.setBackground(Color.GREEN);
}
return componente;
}
}
I figured i could use Repaint(); in the MouseMoved event in the JTable, but i think is not a proper way to fix it... Any help is appreciated, cheers!
Start by changing
String val = getValueAt(rowIndex, columnIndex).toString();
to
String val = getValueAt(rowIndex, 3).toString();
This will ensure that no matter what column the cell represents, you are checking the appropriate columns value - this is why the leading cells are white
You should also consider providing a default color for when the column values doesn't match
if (val.equals("N")) {
componente.setBackground(Color.GREEN);
} else {
componente.setBackground(getBackground());
}
I am writing a utility that will compare metadata fields from a SQL database. I am able to get all of the data into a JTable. I am trying to now color each particular cell depending on if they match the cell of another JTable. From my understanding I need to write a CellRenderer (Change the color of specific rows in my JTable). I had thought doing something like the below to compare the two values would be the best solution
for(int i=0;i<col2;i++){
for(int j=0;j<row2;j++){
if(table1.getValueAt(i,j).equals(table2.getValueAt(i,j))){
table1.setSelectionBackground(Color.GREEN);
table2.setSelectionBackground(Color.GREEN);
}else if(!(table1.getValueAt(i, j).equals(table2.getValueAt(i, j)))){
table1.setSelectionBackground(Color.RED);
table2.setSelectionBackground(Color.RED);
}
}
}
I know the that the setSelectionBackground is not the method I want to call. I'm confused on how to write the CellRenderer listed in the above post to change the background color of a cell in depending if the contents match each other. Is writing the custom CellRenderer the only option?
EDIT 1:
As of right now, it appears to be taking in the correct color for background but it is coloring the entire table rather than a specific cell. Below is my CellRenderer and one of the for loops for how I think I should be calling the setBackground method
private class CellRenderer extends DefaultTableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected,boolean hasFocus,int row, int col){
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
this.setOpaque(true);
this.setBackground(table.getBackground());
return this;
}
int col1 = table1.getColumnCount()-1;
int row1 = table1.getRowCount()-1;
int col2 = table2.getColumnCount()-1;
int row2 = table2.getRowCount()-1;
table1.setDefaultRenderer(Object.class, new CellRenderer());
table2.setDefaultRenderer(Object.class, new CellRenderer());
if(row1>row2){
if(col1>col2){
for(int i=0;i<row2;i++){
for(int j=0;j<col2;j++){
if(table1.getValueAt(i,j).equals(table2.getValueAt(i,j))){
color = Color.GREEN;
System.out.println(color);
table1.setBackground(color);
table2.setBackground(color);
}else if(!(table1.getValueAt(i, j).equals(table2.getValueAt(i, j)))){
color = Color.RED;
System.out.println(color);
table1.setBackground(color);
table2.setBackground(color);
}
}
}
How to set width for cell? I tried trough cell properties, but it does not work
private void addTableCell(Tr tableRow, String content, boolean setWidth, int width) {
Tc tableCell = factory.createTc();
if (setWidth) {
setCellWidth(tableCell, width);
}
tableCell.getContent().add(
wordMLPackage.getMainDocumentPart().
createParagraphOfText(content));
tableRow.getContent().add(tableCell);
}
private void setCellWidth(Tc tableCell, int width) {
TcPr tableCellProperties = new TcPr();
TblWidth tableWidth = new TblWidth();
tableWidth.setW(BigInteger.valueOf(width));
tableCellProperties.setTcW(tableWidth);
tableCell.setTcPr(tableCellProperties);
}
You should also set w:tbl/w:tblGrid; see further ecma376/WordML/Tables
The easiest way to set things appropriately is to make a table to your liking in Word, then generate corresponding code from that using the docx4j webapp, or the Docx4jHelper Word AddIn.
For more on w:tcW, see the spec.
It's possible you need to set the width type for the cell. Try adding
tableWidth.setType("dxa");
before calling setTcW() in your setCellWidth function.
I have VARCHAR in the database for colors. The format is rrr,ggg,bbb (example 225,225,0).
How can I convert that String into java.awt.Color and visualize it in a JSF page?
Do this :
1. Read you color column value
2. Split your string values with , or any other separator you have used
3. Parse each value to Integer value
4. Passed this value into java.awt.color constructors.
Sample Example :
int red,green,blue;
String colorStr = "225,225,0"; //Value from DB
String[] ar_color = colorStr.split(",");
red = Integer.parseInt(ar_color[0]);
green = Integer.parseInt(ar_color[1]);
blue = Integer.parseInt(ar_color[2]);
Color myColor = new Color(red, green, blue);
I would parse the database entry and cast the values to integers, then you can use one of the constructors for a java.awt.color.
However I am not sure that is what you want. You want to use this color value in one of your JSF pages.
You might be setting a color on a component like this :
this.myComponent.setStyle("color:'225,225,0'");
So you could dynamically then change the color like this from the DB :
this.myComponent.setStyle("color:" + myColorStringFromDB);
No need to convert to a java color.
Create a Color object, using the values you have
Color color = new Color(int rrr, int ggg, int bbb)
Example
Color color = new Color(255, 255, 0)
I am creating a text editor using a JTextPane that allows the user to change the color of selected text. But when the user selects the text, then chooses the option to change the color (say, to red) the text does not appear as red until the text is unselected. I tried using setSelectedTextColor to change the color of the selected text, but that doesn't work since that changes the text to red anytime text is selected afterwards. Is there a way to have selected text show up as it's actual color? Or like the way it works in Word where it's not the actual color of the text, but when text of different colors are selected they show up as different colors even when selected.
I use the following code to set up the JTextPane and button that changes the selected text to red:
JButton redButton = new JButton(new StyledEditorKit.ForegroundAction("red", Color.RED));
redButton.setFocusable(false);
buttonPanel.add(redButton);
The JTextPane is set up as with content type HTML and uses the HTMLEditorKit:
p=new JTextPane();
p.setSize(300, 300);
kit = new HTMLEditorKit();
p.setEditorKit(kit);
p.setDocument(kit.createDefaultDocument());
p.setContentType("text/html");
p.setEditable(true);
Let me know if you need more source code to understand the question. Thank You!
Take a look at the DefaultHighlightPainter inner class of DefaultHighlighter.
The method
public void paint(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c) {
Rectangle alloc = bounds.getBounds();
try {
// --- determine locations ---
TextUI mapper = c.getUI();
Rectangle p0 = mapper.modelToView(c, offs0);
Rectangle p1 = mapper.modelToView(c, offs1);
// --- render ---
Color color = getColor();
if (color == null) {
g.setColor(c.getSelectionColor());
}
else {
g.setColor(color);
}
As you can see it uses either getColor() or getSelectionColor(). You can extend the class and adapt the highlight painting.
Or use a simpler approach to override your JTextPane's getSelectionColor(). In the method just check whether text is selected and use attributes of selected elements to get desired ccolor. If nothing is selected just return super.getSelectedColor()
UPDATE:
Actually applying colors for selection is used on low level GlyphView's
public void paint(Graphics g, Shape a) {
...
JTextComponent tc = (JTextComponent) c;
Color selFG = tc.getSelectedTextColor();
if (// there's a highlighter (bug 4532590), and
(tc.getHighlighter() != null) &&
// selected text color is different from regular foreground
(selFG != null) && !selFG.equals(fg)) {
Highlighter.Highlight[] h = tc.getHighlighter().getHighlights();
if(h.length != 0) {
boolean initialized = false;
int viewSelectionCount = 0;
for (int i = 0; i < h.length; i++) {
Highlighter.Highlight highlight = h[i];
int hStart = highlight.getStartOffset();
int hEnd = highlight.getEndOffset();
if (hStart > p1 || hEnd < p0) {
// the selection is out of this view
continue;
}
if (!SwingUtilities2.useSelectedTextColor(highlight, tc)) {
continue;
}
...
As you can see applying selection color vs default color of the view is defined in the SwingUtilities2.useSelectedTextColor(highlight, tc)
In the sources http://kickjava.com/src/com/sun/java/swing/SwingUtilities2.java.htm
public static boolean useSelectedTextColor(Highlighter.Highlight JavaDoc h, JTextComponent JavaDoc c) {
Highlighter.HighlightPainter JavaDoc painter = h.getPainter();
String JavaDoc painterClass = painter.getClass().getName();
if (painterClass.indexOf("javax.swing.text.DefaultHighlighter") != 0 &&
painterClass.indexOf("com.sun.java.swing.plaf.windows.WindowsTextUI") != 0) {
return false;
}
try {
DefaultHighlighter.DefaultHighlightPainter JavaDoc defPainter =
(DefaultHighlighter.DefaultHighlightPainter JavaDoc) painter;
if (defPainter.getColor() != null &&
!defPainter.getColor().equals(c.getSelectionColor())) {
return false;
}
} catch (ClassCastException JavaDoc e) {
return false;
}
return true;
}
So using the color depends on L&F and painter. If you define your onw painter the color won't be used.
It sounds like you may be using something other than a font family name. I re-factored this example to use JTextPane and saw the expected result. As noted there, the actions require a font family name, e.g. the default or face=SansSerif, as specified by the FontFamilyAction class nested in StyledEditorKit.
JTextPane textPane = new JTextPane();
Simplest way to change the color of selected Text :
int start = textPane.getSelectionStart();
int end = textPane.getSelectionEnd();
int selectedLength = end - start;
StyleDocument style = pane.getStyledDocument();
//this give your attribute set of selected Text.
AttributeSet oldSet = style.getCharacterElement(end-1).getAttributes();
//StyleContext for creating attribute set
StyleContext sc = StyleContext.getDefaultStyleContext();
// Attribute set which contains new color with old attributes
AttributeSet s = sc.addAttribute(oldSet, StyleConstants.Foreground, Color.RED);
//This set the color of the Text
style.setCharacterAttributes(start, selectedLength, s, true);
Adding my view. This could be further simple then above approaches.
JEditorPane ep = new JEditorPane() {
#Override
public Color getSelectionColor() {
return COLOR_YOU_WANT;
}
#Override
public Color getSelectedTextColor() {
return COLOR_YOU_WANT;
}
};