I'd like to make a PdfPTable with multiple rows in it. In each row I'd like to have a Radio button in the first cell and descriptive text in the second cell. I'd like all the radio buttons to be a part of the same radio group.
I've used PdfPCell.setCellEvent and my own custom cellEvents in the past to render TextFields and Checkboxes in PdfPTables. However, I can't seem to figure out how to do it with Radio buttons/Radio groups.
Is this possible with iText? Does anyone have an example?
Please take a look at the CreateRadioInTable example.
In this example, we create a PdfFormField for the radio group and we add it after constructing and adding the table:
PdfFormField radiogroup = PdfFormField.createRadioButton(writer, true);
radiogroup.setFieldName("Language");
PdfPTable table = new PdfPTable(2);
// add cells
document.add(table);
writer.addAnnotation(radiogroup);
When we create the cells for the radio buttons, we add an event, for instance:
cell.setCellEvent(new MyCellField(radiogroup, "english"));
The event looks like this:
class MyCellField implements PdfPCellEvent {
protected PdfFormField radiogroup;
protected String value;
public MyCellField(PdfFormField radiogroup, String value) {
this.radiogroup = radiogroup;
this.value = value;
}
public void cellLayout(PdfPCell cell, Rectangle rectangle, PdfContentByte[] canvases) {
final PdfWriter writer = canvases[0].getPdfWriter();
RadioCheckField radio = new RadioCheckField(writer, rectangle, null, value);
try {
radiogroup.addKid(radio.getRadioField());
} catch (final IOException ioe) {
throw new ExceptionConverter(ioe);
} catch (final DocumentException de) {
throw new ExceptionConverter(de);
}
}
}
Taking this a bit further...
If you're nesting a table of radio buttons (radio group) in another table you'll have to change the following from Bruno's example:
instead of
document.add(table);
writer.addAnnotation(radiogroup);
use (assuming you created a parent table and a PdfPCell in that table called parentCell)
parentCell.addElement(table);
parentCell.setCellEvent(new RadioGroupCellEvent(radioGroup));
with a parent cell event like so
public class RadioGroupCellEvent implements PdfPCellEvent {
private PdfFormField radioGroup;
public RadioGroupCellEvent(PdfFormField radioGroup) {
this.radioGroup = radioGroup;
}
#Override
public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
PdfWriter writer = canvases[0].getPdfWriter();
writer.addAnnotation(radioGroup);
}
}
Related
If a user makes a change in the data I want to be able to mark an indication in the row header cell of that row.
I tried a few things but was not successful.
I know that I should set a label to the cell and then decorate the cell with the icon.
I just don't know how to set a label based on the row object to the row header cell. Please help.
natTable.addConfiguration(new AbstractRegistryConfiguration() {
#Override
public void configureRegistry(IConfigRegistry configRegistry) {
configRegistry.registerConfigAttribute(CellConfigAttributes.CELL_PAINTER,
new CellPainterDecorator(new ImagePainter() {
#Override
protected Image getImage(ILayerCell cell, IConfigRegistry configRegistry) {
Person obj = bodyLayerStack.getFilterList().get(cell.getRowIndex());
if (obj.isDirty() {
return dirtyImage;
} else {
return null;
}
}
}, CellEdgeEnum.LEFT, new TextPainter()), DisplayMode.NORMAL, DIRTY_CELL_LABEL);
}
});
How do I set this "DIRTY_CELL_LABEL" label to the row header cell of a particular row (not all rows).
I don't know how to accommodate my conditions in the CellOverrideLabelAccumulator.
You need to implement a custom IConfigLabelAccumulator as explained in our documentation https://www.eclipse.org/nattable/documentation.php?page=styling or the Getting started tutorial https://www.vogella.com/tutorials/NatTable/article.html or even in some posts here on stackoverflow if you search for it, e.g. Adding colors to row in nattable based on condition
For the lazy, here is some code that could be easily added to the NatTable examples. It works with the married property instead of a dirty property that is not available in the NatTable examples:
register an IColumnLabelAccumulator to the row header layer
RowHeaderLayer rowHeaderLayer =
new RowHeaderLayer(rowHeaderDataLayer, bodyLayer, bodyLayer.getSelectionLayer());
rowHeaderLayer.setConfigLabelAccumulator(new IConfigLabelAccumulator() {
#Override
public void accumulateConfigLabels(LabelStack configLabels, int columnPosition, int rowPosition) {
Person person = bodyLayer.getBodyDataProvider().getRowObject(rowPosition);
if (person.isMarried()) {
configLabels.addLabel("MARRIED");
}
}
});
Register the styling
natTable.addConfiguration(new AbstractRegistryConfiguration() {
#Override
public void configureRegistry(IConfigRegistry configRegistry) {
configRegistry.registerConfigAttribute(CellConfigAttributes.CELL_PAINTER,
new CellPainterDecorator(
new TextPainter(),
CellEdgeEnum.LEFT,
new ImagePainter() {
#Override
protected Image getImage(ILayerCell cell, IConfigRegistry configRegistry) {
return image;
}
}),
DisplayMode.NORMAL,
"MARRIED");
}
});
Note that an additional check in the ImagePainter is not needed as the label is only applied to cells with that state.
I have a TableView Column set up as follows, with some text in a Text node. I wanted to style up the text, but the only css property being picked up is the italics. How can I associate the text with other properties such as color.
I've tried text.getStyleClass().add("table-text-allign-top-left"); but only italics gets picked up.
I'd also like to add some kind of spacing, like padding, but I don't know how to add such to an item in a TableCell.
The other problem is how to align items: to the left' right in a TableCell.
Would appreciate it a lot if anyone could help. Thank you all in advance.
This is an extract of the TableView:
clientNames.setCellFactory(new Callback<TableColumn<NewClientPOJO, String>, TableCell<NewClientPOJO, String>>() {
#Override
public TableCell<NewClientPOJO, String> call(TableColumn<NewClientPOJO, String> param) {
final TableCell<NewClientPOJO, String> cell = new TableCell<NewClientPOJO, String>() {
private Text text;
private Text emails;
private Text emails2;
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!isEmpty()) {
text = new Text(item.toString());
// Setting the wrapping width to the Text
text.setWrappingWidth(410);
text.getStyleClass().add("table-text-allign-top-left");
emails = new Text("Good DW TV");
emails.getStyleClass().add("lower");
emails2 = new Text("Scandinavia - Lines cold weather");
emails2.getStyleClass().add("lower");
VBox vbTable = new VBox();
vbTable.getChildren().add(text);
vbTable.getChildren().add(emails);
vbTable.getChildren().add(emails2);
setGraphic(vbTable);
}
}
};
return cell;
}
});
Thanks brian for the reply. I got it to work by changing the Node from Text to a Label. The Label picks up the style class.
I'm currently trying to add some images from a decoded video to a TableView row and they are not appearing. Only empty TableColumns. The TableView has been designed in JavaFx Scene Builder along with the Label.
Here's what I got so far:
public class MainScreenController implements Initializable {
#FXML
private Label previewBoxLabel;
#FXML
private TableView tableView;
private ObservableList<ImageView> imageList = FXCollections.observableArrayList();
#FXML
public void AddClipBeta(){
//Code which uses an external class in order to decode video (Variables Frames, width and height are not shown but are present in the actual code)
VideoSegment clip = new VideoSegment(0, file.getPath(), 0, Frames, width, height);
//Opens the file in decoding class - ready to output frames
try{clip.openFile();} catch(Exception e){}
//First frame is updated on the preview box
previewBoxLabel.setGraphic(new ImageView(convertToFxImage(clip.getThumbnail())));
System.out.println(file.getPath());
int i =0;
//While loop in test phase to see whether or not 10 frames will be visible in the table
while(i != 10){
//Creates and sets columns to tableView
TableColumn<ImageView, ImageView> col = new TableColumn<ImageView, ImageView>();
col.setPrefWidth(100); //Set width of column
tableView.getColumns().add(col);
col.setCellFactory(new Callback<TableColumn<ImageView, ImageView>, TableCell<ImageView, ImageView>>() {
#Override
public TableCell<ImageView, ImageView> call(TableColumn<ImageView, ImageView> p) {
TableCell<ImageView, ImageView> cell = new TableCell<ImageView, ImageView>(){
};
return cell;
}
});
//Adds current frame to list
imageList.add(new ImageView(convertToFxImage(clip.getThumbnail())));
//Gets next video frame
try{clip.getNextFrame();} catch(Exception e){}
//Updates counter
i++;
}
//Sets list of frames on the table
tableView.setItems(imageList);
}
// There is a problem with this implementation: transparent pixels on the BufferedImage aren't converted to transparent pixels on the fxImage.
public static javafx.scene.image.Image convertToFxImage(java.awt.image.BufferedImage awtImage) {
if (Image.impl_isExternalFormatSupported(BufferedImage.class)) {
return javafx.scene.image.Image.impl_fromExternalImage(awtImage);
} else {
return null;
}
}
I've been struggling understanding how the TableView works the last couple of days and it would be a real breakthrough if we could get to the bottom of this.
Thanks for reading and any help in advance!
When setting a CellFactory, you need to take in to account that it will override some default bevaiours such as setting text and images.
For example. I had to create a ListView of Applications that launched on double click. I had to set a CellFactory in order to add a listener to the mouse click of each individual cell.
applications.setCellFactory(new Callback<TreeView<Application>, TreeCell<Application>>() {
#Override
public TreeCell<Application> call(TreeView<Application> param) {
return new TreeCell<Application>() {
#Override
protected void updateItem(Application item, boolean empty) {
//call the origional update first
super.updateItem(item, empty);
//the root item in my list is null, this check is required to keep a null pointer from happening
if (item != null) {
// text and graphic are stored in the Application object and set.
this.setText(item.getApplicationListName());
this.setGraphic(item.getGraphic());
// registers the mouse event to the cell.
this.setOnMouseClicked((MouseEvent e) -> {
if (e.getClickCount() == 2) {
try {
this.getItem().launch(tabBar);
} catch (UnsupportedOperationException ex) {
Dialogs.create().nativeTitleBar().masthead("Comming Soon™").message("Application is still in development and will be available Soon™").nativeTitleBar().title("Unavailable").showInformation();
}
} else {
e.consume();
}
});
}else if(empty){
this.setText(null);
this.setGraphic(null);
this.setOnMouseClicked(null);
}
}
};
}
});
This was pieced together from some other code so if there is anything else you would like explained, let me know!
I managed to sort this out with the help of you guys. Basically, what I did was make a class with a bunch of setters and getters and a constructor that takes in ImageViews and sets it to a variable in the class via it's constructors. Then I went back to my code and added the following:
Class with Getters and Setters:
import javafx.scene.image.ImageView;
public class tableDataModel {
private ImageView image;
public tableDataModel(ImageView image){
this.image = image;
}
public ImageView getImage(){
return image;
}
public void setImage(ImageView image){
this.image = image;
}
}
Code from MainScreenController:
TableColumn<tableDataModel, ImageView> col = new TableColumn<>();
tableView.getColumns().add(col);
imageList.add(new tableDataModel(new ImageView(convertToFxImage(clip.getThumbnail()))));
col.setPrefWidth(50);
col.setCellValueFactory(new PropertyValueFactory<tableDataModel, ImageView>("image"));
int i = 0;
while (i != 10) {
try {
imageList.add(new tableDataModel(new ImageView(convertToFxImage(clip.getNextFrame()))));
} catch (Exception e) {
}
i++;
}
tableView.setItems(imageList);
I am using nebula gridTableViewer for my application, in its cell some time content is so lengthy, so I want to show as WRAP (in multiline). I did changes for it but it is not reflecting:
I added SWT.WRAP but not works, I tried to wrap the text in LabelProvider too but it also not works so how could i do it?
Should i need to add listener for this.
Adding SWT.WRAP to the gridTableViewer would not cause the Text in the grid cells to wrap.
gridColumn.setWordWrap(true) causes the text entered in the cell to be wrapped after the entered value is applied to the editor(setvalue called). To wrap the text interactively, SWT.WRAP should be added as a style to the TextCellEditor or to Text widget placed in the cells.
gridViewerColumn.getColumn.setWordWrap(true);
gridTableViewer.setEditingSupport(new EditingSupport(gridTableViewer) {
....
#Override
protected CellEditor getCellEditor(Object element) {
TextCellEditor cellEditor = new TextCellEditor(gridTableViewer.getGrid(),
SWT.WRAP)
return cellEditor;
}
Or
....
final GridItem item = grid.getItem(grid.getTopIndex());
for (int i = 0; i < grid.getColumnCount(); i++) {
final Text text = new Text(grid, SWT.WRAP);
Listener textListener = new Listener() {
public void handleEvent(final Event e) {
switch (e.type) {
case SWT.FocusOut:
item.setText(column, text.getText());
....
}
}
}
}
I have used the SWT.WRAP in the TextCellEditor before, and it works.
I am working on Eclipse plugin. Here i created a separate view and now i want to format the color of tree node.
These are code present in createpartcontrol method.
ScrolledComposite sc = new ScrolledComposite(parent, SWT.V_SCROLL );
Composite composite1 = new Composite(sc, SWT.NONE);
Composite composite_1 = creatingcomposite(composite1);
Tree tree = new Tree(composite_1, SWT.FULL_SELECTION );
TreeItem item = new TreeItem(tree, SWT.NONE);
here i want to set some colour like blue.
item.setText("This is sparta");
Now here i want some different colour like yellow on subsubitem text.
TreeItem subsubItem = new TreeItem(subItem, SWT.NONE);
subsubItem.setText(new String[] { "Function Name: "+ errorPreTest11.description.get(j).function });
For doing this i tried to set SWT.COLOR_BLUE but it's not working.
Use
item.setForeground(tree.getDisplay().getSystemColor(SWT.COLOR_BLUE));
You can also create your own colors but if you do this you must dispose of them when you are done.
I suggest you using the TreeViewer. In this case you would have a functionality to set a LabelProvier on your viewer. Label provider has a subclass called StyledCellLabelProvider, which you can successfully extend to provide styling of your labels like this: (Please also see a TextStyle class for more formating options).
public class MyStyledLabelProvider extends StyledCellLabelProvider {
private Styler defaultStyler;
public MyStyledLabelProvider () {
defaultStyler = new Styler() {
#Override
public void applyStyles(TextStyle textStyle) {
textStyle.strikeout = true;
}
};
}
#Override
public void update(ViewerCell cell) {
Object element = cell.getElement();
StyledString styledString = getStyledString(element);
cell.setText(styledString.toString());
cell.setStyleRanges(styledString.getStyleRanges());
super.update(cell);
}
#SuppressWarnings("unchecked")
private StyledString getStyledString(Object element) {
return new StyledString("Cell string", defaultStyler);
}
}