so I am using JavFX to create a form that stores all the answers in a csv file. I need to create a dropdown menu that allows the users to select an option, which is then recorded in the csv file. I have tried a lot of different options, however I think comboBox is the best option.
I have no problem creating the ComboBox, I only run into problems when it comes to the method to get the value of the box.
Can someone help me find a solution, or suggest what another JavaFX menu I can use?
This is the code I have right now:
public VBox setFamiliar(){
Button button = new Button();
button.setOnAction(e -> toString());
familiarComboBox = new ComboBox<>();
familiarVBox = new VBox();
familiarComboBox.getItems().addAll("Irmão", "Irmã", "Avó", "Avô", "Tio", "Tia", "Pai", "Mãe");
familiarVBox.getChildren().add(familiarComboBox);
familiarVBox.getChildren().add(button);
return familiarVBox;
}
Here I set the ComboBox, this part doesnt seem to have a problem because it appears and I can select an item. I created a separate void toString() method that sets the value of a variable to the current selected item
public void toString(ActionEvent e){
familiar = familiarComboBox.getSelectionModel().getSelectedItem().toString();
}
The problem is then in the get method to get the value that was selected.
public String getIrmao(){
if(familiar.equals("Irmão")){
return "2";
}
return "0";
I also tried to do familiarComboBox.getSelectionModel().getSelectedItem().equals(), and other variations of this combination.
If I understand your requirement -- that when a user makes a choice from the "Familiar" combo box, a value should be written immediately to a CSV file -- you don't need the getIrmao() method. You simply write the value out in the action which you are calling toString(...) (not a good choice of names), but which we will rename to handleFamiliarChange(...).
Now the method becomes
public void handleFamiliarChange(ActionEvent e){
final String familiar =
familiarComboBox.getSelectionModel().getSelectedItem().toString();
FileUtils.writeToCsvFile(familiar.equals("Irmão") ? 2 : 0);
}
where FileUtils.writeToCsvFile(...) is a method that does the file writing. Note that FileUtils is a class you have created to separate out file handling concerns -- your JavaFX view class should only concern itself with views.
Related
I am creating a pdf where the title of each pdf page would be customized based on the current page number. For example, in the 1st page the title is "First Page", and in the 2nd page the title is "Second Page", and so on...
What we do now is we add the title to a PdfPTable, then we add a lot of other stuff to the PdfPTable as well, so this PdfPTable contains several pages of data. Finally we add this large PdfPTable object to document. Now we want to use the onStartPage() method in PdfPageEventHelper to get the current page number so that we can customize the title for each page.
The problem is onStartPage() does not trigger until we add that large PdfPTable object to the document, which means we cannot make the resource bundle to load different key values before the PdfPTable object is added to the document, right? Any suggestion to realize this?
--------------------we have codes like below-------------------------------------
Phrase title = new Phrase();
title.add(new Chunk(bundle.getString(pdfNewPageEventHandler.getKey()), headerFont));
PdfPCell cell = new PdfPCell(new Paragraph(
new Phrase(title)));
.........
PdfPTable table = new PdfPTable(tableSize);
table.addCell(cell);
.........
document.add(table);
private class PdfNewPageEventHandler extends PdfPageEventHelper {
private int currentPageNum = 0;
private String key;
#Override
public void onStartPage(PdfWriter writer, Document document) {
currentPageNum = currentPageNum + 1;
if (currentPageNum == 1) {
key = "firstPage";
}
else if (currentPageNum == 2) {
key = "secondPage";
}
}
public String getKey() {
return key;
}
}
I have more than one answer. I don't know which one applies to your specific situation:
Don't ever add content in the onStartPage() method. As documented, all content should be added in the onEndPage() method.
It's not always wise to create one large table (it builds up in memory) and then add the table to the document (only at this moment, memory can be freed). Maybe you want to try out some of the large table strategies from the documentation.
In some cases, building a table in memory and then adding it to the document is the only strategy you can use. iText will then distribute the content of the table over different pages, triggering page events. However: if you want to trigger events that are specific to the table, you can also define events at the level of the table. There's a PdfPTableEventSplit and a PdfPTableEventAfterSplit class for this exact purpose.
The code sample you provided, didn't really illustrate the problem. Can you please rephrase the problem, as I'm not sure if any of my answers go to the core of the problem.
I have a simple JavaFX app that allows the user to query a database and see the data in a table.
I'd like to allow the user to be able to click a table cell and copy text from that cell to the clipboard with the standard clipboard key stroke: ctrl-c for Win/Linux or cmd-c for Mac. FYI, the text entry controls support basic copy/paste by default.
I'm using the standard javafx.scene.control.TableView class. Is there a simple way to enable cell copy? I did some searches and I see other people create custom menu commands... I don't want to create a custom menu, I just want basic keyboard copy to work with single cells.
I'm using single selection mode, but I can change to something else if need be:
TableView<Document> tableView = new TableView<Document>();
tableView.getSelectionModel().setCellSelectionEnabled(true);
tableView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
You just have to create a listener in the scene, something like:
scene.getAccelerators()
.put(new KeyCodeCombination(KeyCode.C, KeyCombination.CONTROL_ANY), new Runnable() {
#Override
public void run() {
int row = table.getSelectionModel().getSelectedIndex();
DataRow tmp = table.getItems().get(row);
final Clipboard clipboard = Clipboard.getSystemClipboard();
final ClipboardContent content = new ClipboardContent();
if(table.getSelectionModel().isSelected(row, numColumn)){
System.out.println(tmp.getNumSlices());
content.putString(tmp.getNumSlices().toString());
}
else{
System.out.println(tmp.getSelected());
content.putString(tmp.getSelected());
}
clipboard.setContent(content);
}
});
For a complete example, you can download it at the gist.
I recommended that you review this post, work for me
http://respostas.guj.com.br/47439-habilitar-copypaste-tableview-funcionando-duvida-editar-funcionalidade
The author use an aditional util java class for enable the cell content copy from a tableView
I have an application that I am building that has a table in it, I'm not using a tableview to build this table because I need each row to be able to expand similar to an accordion. I was able to achieve what I need by using a timeline and looping through the data and building each row (its kind of crude right now since I'm still working with dummy data eventually it will be a list iterator and not just a for loop) but I'm not happy with how its done. There are a lot of default values that will never change so I don't really need to set them in my worker class every time, I decided to just add them to the object class that I put together. So basically, at a high level it looks something like this:
for (int i = 0; i < 30; i++) {
RowBuilder builder = new RowBuilder(tableBox, i);
try {
builder.run();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I'm passing it the parent which is a VBox - tableBox, then I'm passing the count for later use.
Inside the RowBuilder I'm getting a new instance of the object DashboardRow which has all the defaults set in it, then I'm setting the data for each row and returning the DashboardRow.
Here is an example of a getter setting values in the DashboardRow
public HBox getMainRow() {
mainRow.setAlignment(Pos.CENTER_LEFT);
mainRow.setPrefHeight(60);
mainRow.setMinHeight(60);
mainRow.setMaxHeight(60);
mainRow.setPrefWidth(-1);
mainRow.setStyle("-fx-background-color:#FFFFFF;");
return mainRow;
}
Inside the DashboardRow class I have a ton of new objects being created for every element I need in the row. There are 21 for each row, mostly VBox, HBox and StackPane to build the actual row, the rest are just labels and buttons.
This is what is looks like so far. Opened and closed states.
Is there a better way to dynamically build things like this in javafx? I'm basically pulling data from a database and looping through that data to populate a row.
I can't comment but it may be an answer anyway. Why can't you use the setGraphic method of a custom table cell and put the accordion node in a table. setGraphic takes any kind of node.
It sounds simpler than what you're doing.
I just tried it out with the Oracle sample and it works great.
I added
Callback<TableColumn<Person, String>, TableCell<Person, String>> accCellFactory
= new Callback<TableColumn<Person, String>, TableCell<Person, String>>() {
#Override
public TableCell call(TableColumn p) {
TitledPane t1 = new TitledPane("T1", new Button("B1"));
TitledPane t2 = new TitledPane("T2", new Button("B2"));
TitledPane t3 = new TitledPane("T3", new Button("B3"));
Accordion accordion = new Accordion();
accordion.getPanes().addAll(t1, t2, t3);
TableCell tc = new TableCell();
tc.setGraphic(accordion);
return tc;
}
};
and changed this line firstNameCol.setCellFactory(accCellFactory);
and I get
Of course you might want something other than buttons but I just copied the Accordion sample from the javadoc.
I'm creating a basic CSV importer tool. The goal is for a RunBase class to call a dialog, and in the dialog, I want to have the user select a CSV file that will be a specific format.
I have dialog.allowUpdateOnSelectCtrl(true) so the idea is when they choose a file, I can read in the first row and create a preview in a listview the same way as the Data Import/Export tool does.
This is all my dialog is so far:
public Object dialog()
{
DialogRunbase dialog = super();
container conFilter = ["Comma Seperated Value .txt ", "*.csv"];
#resAppl
;
dialog.filenameLookupFilter(conFilter);
dialog.allowUpdateOnSelectCtrl(true);
dlgFileName = dialog.addFieldValue(typeid(filenameSave),filenameSave);
return dialog;
}
I realize that I could create a custom form and other options. I'd like to try and do it this way so I can learn this method.
I create a menu dynamically. I add several checkable actions into one menu. Sometimes actions may have the same text that user sees. It's up to user (actually user adds commands into menu).
The problem is in this case clicking works wrong. If I click on the first action (from 2 with the same texts) everything is good but if I click on the second one, both actions are selected. I don't understand why. The code where actions have been created is here:
for (int i = 0; i< currentList.size(); i++)
{
QString lanKey = currentList.at(i)->Language->toString();
QAction* lanAction = new QAction(this);
QString name ="action_" + currentList.at(i)->Id->toString();
lanAction->setObjectName(name);
lanAction->setText(lanKey);
lanAction->setCheckable(true);
lanAction->setData(i);
connect(lanAction, SIGNAL(triggered(bool)), this, SLOT(ShowSomething(bool)));
ui->menuMy->addAction(lanAction);
}
Here, lanKey is language that may be the same for different actions. Anyway click on the specific action should lead only to checking of this action. What's wrong?
The slot is here:
void VMainWindow::ShowSomething(bool IsTriggered)
{
QAction* senderAction = (QAction*)sender();
int listIndex = senderAction->data().toInt();
if (IsTriggered)
{
CreateEditor(subtitles, listIndex);
}
else
{
//hide this editor
QString name = "editor" + editorsList->Id->toString();
QDockWidget* editorDock = this->findChild<QDockWidget*>(name);
if (editorDock != 0)
{
this->removeDockWidget(editorDock);
this->setLayout(layout());
}
}
}
Thanks
The source of problem is found: it turned out that the slot finds the checked action wrong - by text, not by id.
I can't find a logical issue in the code you posted so far. Here are a couple of options which I would try in order to resolve this problem:
Limit the users possibilities when adding items to a menu so that he can't add two items with the same name.
Add qDebug() output to ShowSomething to see if there is a problem with signals&slots. For example, if the slot gets called once for the first item but twice for the second item there is a problem there.
Debug into CreateEditor step-by-step.
As the problem seems to appear only for actions with a similar name, you should make sure that you never make a lookup of an action (or something related) by its text() but rather by its data() or objectName() (assuming that currentList.at(i)->Id will always be unique)