I ran out of ideas on how to perform search in table layout using textfield. I just want to match the text of textfield with 1st column text, if it exist, show the entire row containing that text.I have done it in list and table component but in table layout everything i do is just not working. Any help is appreciated.
TableLayout tl1 = new TableLayout(1, 2);
Container containerTableData = new Container(tl1);
for (int i = 1; i < 3; i++) {
Container tableNameDataContainer = new Container(new FlowLayout(Component.CENTER, Component.CENTER));
tableNameData = new TextArea("Table Name " + i);
tableNameDataContainer.add(tableNameData);
Container inaugurationDateDataContainer = new Container(new FlowLayout(Component.CENTER, Component.CENTER));
inaugurationDateData = new TextArea("Inauguration Date 1");
inaugurationDateDataContainer.add(inaugurationDateData);
containerTableData.add(tl1.createConstraint().widthPercentage(50), tableNameDataContainer);
containerTableData.add(tl1.createConstraint().widthPercentage(50), inaugurationDateDataContainer);
containerTableData.revalidate();
}
TextField searchTextField = new TextField();
searchTextField.addDataChangeListener(new DataChangedListener() {
#Override
public void dataChanged(int type, int index) {
String getTextAreaData = tableNameData.getText();
String getTextField = searchTextField.getText();
if (getTextAreaData.startsWith(getTextField)) {
}
}
}
Update 1:
To add black and white strips design to the table as in fig below:
Mycode so far:
for (int i = 1; i < 3; i++) {
Container tableNameDataContainer = new Container(new FlowLayout(Component.CENTER, Component.CENTER));
tableNameData = new TextArea("Table Name " + i);
tableData(tableNameData, i, tableNameDataContainer);
tableNameDataContainer.add(tableNameData);
Container inaugurationDateDataContainer = new Container(new FlowLayout(Component.CENTER, Component.CENTER));
inaugurationDateData = new TextArea("Inauguration Date 1");
tableData(inaugurationDateData, i, inaugurationDateDataContainer);
inaugurationDateDataContainer.add(inaugurationDateData);
containerTableData.add(tl1.createConstraint().widthPercentage(50), tableNameDataContainer);
containerTableData.add(tl1.createConstraint().widthPercentage(50), inaugurationDateDataContainer);
}
method to add desired style
public void tableData(TextArea textAreaName, int i, Container c) {
textAreaName.setName(textAreaName.getText());
c.setName("c" + i);
zeroPaddingMargin(textAreaName);
zeroPaddingMargin(c);
textAreaName.setUIID(textAreaName.getText());
textAreaName.getAllStyles().setFont(Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL));
textAreaName.setEditable(false);
textAreaName.setGrowByContent(true);
textAreaName.setGrowLimit(2);
textAreaName.getAllStyles().setBgTransparency(0);
c.getAllStyles().setBgTransparency(255);
textAreaName.getAllStyles().setFgColor(0x000000);
if (i % 2 == 0) {
c.getAllStyles().setBgColor(0xcccccc);
} else {
c.getAllStyles().setBgColor(0xffffff);
}
textAreaName.getAllStyles().setPadding(0, 0, 0, 0);
textAreaName.getAllStyles().setMargin(0, 0, 0, 0);
textAreaName.getAllStyles().setAlignment(Component.CENTER);
}
public void zeroPaddingMargin(Component a) {
a.setUIID("Uiid" + a.getName());
a.getAllStyles().setPadding(0, 0, 0, 0);
a.getAllStyles().setMargin(0, 0, 0, 0);
}
The black and white strip style in table rows appears as abov img at first but all the styles disappears as soon as i search in the textfield. I managed to achieve those styles somehow though i think it is not the standard way to do that. Is there any standard way to achieve that?
Didn't try it but I'm guessing this should work. It will require making containerTableData final:
searchTextField.addDataChangeListener(new DataChangedListener() {
#Override
public void dataChanged(int type, int index) {
String getTextField = searchTextField.getText().toLowerCase();
int counter = 0;
boolean show = false;
for(Component c : containerTableData) {
if(counter % 2 == 0) {
Container cnt = (Container)c;
TextArea ta = (TextArea)cnt.getComponentAt(0);
show = ta.getText().toLowerCase().indexOf(getTextField) > -1);
}
counter++;
c.setHidden(!show);
c.setVisible(show);
}
containerTableData.animateLayout(200);
}
}
Edited the answer to hide/show the entire row. It relies on searching only in the first column and on there being two columns but that should be easily adaptable.
Related
I have one button in place. For each number a user sets in a text field, the appropriate number of buttons adds to the ui. But for every change of number i want all the buttonAdded to be removed, but not the first one, that is already in place. How do i do that? It didn't work when i tried it like in the exmaple:
final int number = Integer.parseInt(this.textField.getValue());
if(number > 1) {
for(int i = 1; i < number; i++) {
final XdevButton buttonAdded = new XdevButton("Button " + i);
this.verticalLayout.removeComponent(buttonAdded);
this.verticalLayout.addComponent(buttonAdded);
}
}
Is there a way to create new buttons with a defined component name in my loop?
Something like this:XdevButton button + i = new XdevButton()?
Edit:(Tried it with a list) - doesn't work.
private void textField_valueChange(final Property.ValueChangeEvent event) {
final int number = Integer.parseInt(this.textField.getValue());
final List<XdevButton> addedButtons = new LinkedList<>();
for(final XdevButton btn : addedButtons) {
this.verticalLayout.removeComponent(btn);
}
addedButtons.clear();
if(number > 1) {
for(int i = 1; i < number; i++) {
final XdevButton buttonAdded = new XdevButton("Button " + i);
addedButtons.add(buttonAdded);
for(final XdevButton btn : addedButtons) {
this.verticalLayout.addComponent(btn);
}
}
}
}
What am i missing?
That indeed won't work, nor is it possible to name a button the way you are asking.
You have a few options, if you don't want to reuse the old buttons.
If the vertical layout only contains buttons, or if you know how many components there are before the buttons, you can remove them by index:
for(int i = 1; i < number; i++) {
this.verticalLayout.getElement().removeChild(i);
}
You can also create a list or other collection to keep track of the buttons, this way you can reuse them as well:
private List<Button> buttons = new LinkedList<>();
...
// Not enough buttons, need to add new ones
if (number > buttons.size()) {
for(int i = buttons.size(); i < number; i++) {
Button buttonAdded = new Button("Button " + i);
buttons.add(buttonAdded);
}
}
// Too many buttons, remove the extras
else if (buttons.size() > number) {
List<Button> buttonsToRemove = buttons.subList(number, buttons.size());
buttonsToRemove.forEach(verticalLayout::remove);
buttonsToRemove.clear();
}
I would create a separate layout holder for buttons to be removed/added and work with it. For testing purposes I've replaced your XdevButton with a general Vaadin Button class. This seems to work according to your specs:
#Route("customView")
public class CustomView extends VerticalLayout {
VerticalLayout buttonHolder=new VerticalLayout();
public CustomView (){
TextField tf=new TextField("Enter amount of buttons");
tf.addValueChangeListener(event->{
final int number = Integer.parseInt(event.getValue());
if(number > 1) {
buttonHolder.removeAll();
for(int i = 0; i < number; i++) {
final Button buttonAdded = new Button("Button " + i);
buttonHolder.add(buttonAdded);
}
}
});
Button alwaysInPlace=new Button("This button is never removed");
add(alwaysInPlace);
add(buttonHolder);
}
}
Example is created in V14, but should be similar in all other versions
I want to make ToDoList App. After successfully adding task to do (which contains checkbox, JLabel and date, all putted in a box) i want to remove them dynamically. With adding it's not problem but when i try to remove (ater clicking checked in checkbox) it works only once. Then it either removes not once which are intended or not removing them at all. I am not sure why it's not working so I paste all code below.
JSpinner dateSpin;
Box eventBox, boxBox;
Box[] taskBox = new Box[1000];
JTextField eventName;
Date date;
Checkbox[] doneCheck = new Checkbox[1000];
JLabel taskLabel;
JPanel panel;
JScrollPane scrollPane;
SimpleDateFormat simpleDate;
int i = 0;
public static void main(String[] args) {
new Main();
}
private Main(){
this.setSize(400, 600);
this.setTitle("To-Do List");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setLocationRelativeTo(null);
panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
boxBox = Box.createVerticalBox();
scrollPane = new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
eventBox = Box.createHorizontalBox();
eventBox.setBorder(BorderFactory.createEtchedBorder());
JLabel plusSign = new JLabel("+");
plusSign.setFont(new Font("Serafi", PLAIN, 20));
plusSign.setMaximumSize(new Dimension(Integer.MAX_VALUE, plusSign.getMinimumSize().height));
eventBox.add(plusSign);
eventName = new JTextField(20);
eventName.setFont(new Font("Times", Font.ITALIC, 15));
eventName.setMaximumSize(new Dimension(Integer.MAX_VALUE, eventName.getMinimumSize().height));
eventName.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == eventName){
/* to do: saving every task in some file, figure out how to remove
those tasks (checkbox + jlabel) -> whole box from screen or how to send them to "done"
also "done" to do*/
simpleDate = new SimpleDateFormat("E-dd-MM-yyyy");
taskBox[i] = Box.createHorizontalBox();
taskBox[i].setBorder(BorderFactory.createTitledBorder(simpleDate.format(date)));
doneCheck[i] = new Checkbox();
doneCheck[i].addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
int k = 0;
for (int j = 0; j < doneCheck.length; j++) {
if(doneCheck[j].getState()){
//remove(doneCheck[k]);
//System.out.println("?" + i + "?" + k + " " + e.getSource().toString());
System.out.println("xxxxx" + doneCheck[j].getState());
break;
}
System.out.println("oooooo");
k++;
}
System.out.println(doneCheck.length + taskBox[k].toString());
//System.out.println("! " + k + " " + e.getSource().toString());
boxBox.remove(taskBox[k]);
//boxBox.removeAll();
boxBox.revalidate();
boxBox.repaint();
}
});
taskBox[i].add(doneCheck[i]);
String taskName = eventName.getText();
taskLabel = new JLabel(taskName);
taskLabel.setMinimumSize(new Dimension(500,10));
taskLabel.setPreferredSize(new Dimension(300, 10));
taskBox[i].add(taskLabel);
boxBox.add(taskBox[i]);
boxBox.setMaximumSize(new Dimension(Integer.MAX_VALUE, boxBox.getMinimumSize().height + 11));
panel.add(boxBox);
panel.revalidate();
panel.repaint();
i++;
}
}
});
eventBox.add(eventName);
date = new Date();
dateSpin = new JSpinner(new SpinnerDateModel(date, null, null, Calendar.DAY_OF_MONTH));
JSpinner.DateEditor dateEditor = new JSpinner.DateEditor(dateSpin, "dd/MM/yy");
dateSpin.setEditor(dateEditor);
dateSpin.setMaximumSize(new Dimension(Integer.MAX_VALUE, dateSpin.getMinimumSize().height));
dateSpin.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
if(e.getSource() == dateSpin){
date = (Date) dateSpin.getValue();
}
}
});
eventBox.add(dateSpin);
panel.add(eventBox, new FlowLayout());
this.add(scrollPane);
this.setVisible(true);
}
You never remove elements from the taskBox and doneCheck arrays.
Now if you mark the first entry as done, your ItemListener will always find this first entry when looping over the doneCheck array.
Marking the entries as done in reverse order (always the last shown entry) will remove one entry after the other.
As to your software design: it's considered bad practice to manage your data in several parallel arrays.
Please consider creating a custom class for the todo items that manages all the elements of a single todo item.
Unless you are initializing doneCheck items somewhere, this:
Checkbox[] doneCheck = new Checkbox[1000];
And this:
int k = 0;
for (int j = 0; j < doneCheck.length; j++) {
if (doneCheck[j].getState()) {
--------^^^^^^^^^^^^
Is probably one the reason it fails: you probably got a NullPointerException somewhere, eg: when value of j > 0. The NPE will probably be catched by the EventDispatchThread which may or may not be kind enough to show it on stderr...
I fail to see why you are using this array, and you can shorten your code and avoid NPE like this:
Checkbox cb = new Checkbox();
cb.addItemListener(event -> {
if (cb.getState()) { // not null!
boxBox.remove(cb);
boxBox.revalidate();
boxBox.repaint();
}
});
doneCheck[i] = cb; // I still don't know why you need that.
My guess is that you have 2 variables global int i = 0 and local int k = 0 in here
public void itemStateChanged(ItemEvent e) {
// int k = 0;//<-------- LOCAL
for (int j = 0; j < doneCheck.length; j++) {
if(doneCheck[j].getState()){
//Either k = j;
boxBox.remove(taskBox[j]);
//remove(doneCheck[k]);
//System.out.println("?" + i + "?" + k + " " + e.getSource().toString());
System.out.println("xxxxx" + doneCheck[j].getState());
break;
}
System.out.println("oooooo");
//k++;//<-- ALWAYS == last j value before the break;
}
System.out.println(doneCheck.length + taskBox[k].toString());
//System.out.println("! " + k + " " + e.getSource().toString());
//boxBox.remove(taskBox[k]);//
//boxBox.removeAll();
boxBox.revalidate();
boxBox.repaint();
}
Every time you call for itemStateChanged int k = 0; will be initialized to 0 and you will be removing element[j] from array of taskBox. As you k++ statement will be equal to the last j value before the break; because it sits after the if(doneCheck[j].getState()){...
Try moving boxBox.remove(taskBox[j]); inside the for loop and using j instead of k.
I have the following code, that allows me to remove a row from the right Jtable with a click. It works fine for all the rows, except when there is only one row remaining. BTW, sorry for most names being in portuguese, its my native language. Here are the images showing before and after i click the final row in the table. It updates the total, but the row remains. For every other case, it works perfectly.
Screenshot:
private void jtbSelecionadosMouseClicked(java.awt.event.MouseEvent evt)
{
int x = jtbSelecionados.rowAtPoint(evt.getPoint());
if (x >= 0)
{
String nomeProduto = (String)jtbSelecionados.getModel().getValueAt(x, 0);
for (int i = 0; i < itensVenda.size();i++)
{
if (itensVenda.get(i).getNomeProduto().equals(nomeProduto))
{
if(itensVenda.get(i).getQtd() > 1)
{
valorTotal -= (itensVenda.get(i).getPreco() / itensVenda.get(i).getQtd());
double precototal = itensVenda.get(i).getPreco();
double unit = precototal / itensVenda.get(i).getQtd();
System.out.println("Unidade: "+unit+"\nTotal: "+precototal);
itensVenda.get(i).setPreco(itensVenda.get(i).getPreco() - (itensVenda.get(i).getPreco() / itensVenda.get(i).getQtd()));
itensVenda.get(i).setQtd(itensVenda.get(i).getQtd() - 1);
recarregarTabela();
}
else if(itensVenda.get(i).getQtd() <= 1)
{
valorTotal -= itensVenda.get(i).getPreco() / itensVenda.get(i).getQtd();
itensVenda.remove(i);
recarregarTabela();
}
}
}
}
function that resets the table with new information:
private void recarregarTabela()
{
if (itensVenda.size() == 0)
{
dtm.getDataVector().removeAllElements();
dtm.setRowCount(0);
lblTotal.setText("Total: R$" + String.valueOf(valorTotal));
}
else
{
dtm.getDataVector().removeAllElements();
dtm.setRowCount(0);
for (Item item : itensVenda)
{
Object[] vetor = new Object[3];
vetor[0] = item.getNomeProduto();
vetor[1] = item.getQtd();
vetor[2] = String.format("%.2f", item.getPreco());
System.out.println(item.getPreco());
dtm.addRow(vetor);
}
lblTotal.setText("Total: R$" + String.valueOf(valorTotal));
}
}
You dont have to rebuild whole model everytime a single row is deleted. As you already have index of clicked or selected row you can just remove it from model using removeRow(index) method. I suspect that dtm is a DefaultTableModel so just call dtm.removeRow(index) everytime you need to remove row from table
I want to swap two texts in TableItems. Firstly, I set the text, then I check which TableItems are selected, save them in 2 variables and overwrite them. But I get these strings instead of the message I wanted:
[Lorg.eclipse.swt.widgets.TableItem;#6fadae5d
The part after the # is always different, I guess it's an ID or something but I can't find a solution. Here's the code snippets. groupsList is a String array.
for (int i = 1; i <= logic.amountOfGroups; i++) {
Table table = new Table(shell, SWT.MULTI | SWT.BORDER);
table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
for (int j = 0; j < logic.personsInGroup; j++) {
TableItem tableItem_1 = new TableItem(table, SWT.NONE);
tableItem_1.setText(logic.groupsList.get(i - 1)[j]);
}
tableList.add(table);
}
So I wrote the content into the TableItems, then I want to swap them:
swapButton = new Button(shell, SWT.NONE);
swapButton.setText("Swap");
swapButton.addMouseListener(new MouseAdapter() {
#Override
public void mouseDown(MouseEvent e) {
int[] playerIndices = new int[2];
int[] groupIndices = new int[2];
int i = 0;
String toBeSwappedZero = "";
String toBeSwappedOne = "";
for (Table table : tableList) {
if (table.getSelectionCount() == 1) {
if (toBeSwappedZero == "") {
groupIndices[0] = i;
playerIndices[0] = table.getSelectionIndex();
toBeSwappedZero = table.getSelection().toString();
} else {
groupIndices[1] = i;
playerIndices[1] = table.getSelectionIndex();
toBeSwappedOne = table.getSelection().toString();
}
}
if (table.getSelectionCount() == 2) {
playerIndices = table.getSelectionIndices();
groupIndices[0] = i;
groupIndices[1] = i;
toBeSwappedZero = table.getItem(playerIndices[0]).getText();
toBeSwappedOne = table.getItem(playerIndices[1]).getText();
}
i++;
}
System.out.println(toBeSwappedOne);
tableList.get(groupIndices[0]).getItem(playerIndices[0]).setText(toBeSwappedOne);
tableList.get(groupIndices[1]).getItem(playerIndices[1]).setText(toBeSwappedZero);
}
});
Here's the GUI
Take a look these lines in your MouseAdapter:
if (table.getSelectionCount() == 1) {
if (toBeSwappedZero == "") {
// ...
toBeSwappedZero = table.getSelection().toString();
} else {
// ...
toBeSwappedOne = table.getSelection().toString();
}
}
Notice that Table.getSelection() returns an array of TableItem objects. As #greg-449 pointed out, you'll get [Lorg.eclipse.swt.widgets.TableItem;#XXXXXXXX if you call toString() on that array.
In each of those two cases you've already checked that there is only one TableItem selected, so you can safely do table.getSelection()[0] to access that TableItem (Alternatively, you could do table.getItem(table.getSelectionIndex()) after verifying that there is at least one and only one item selected).
In an unrelated if-statement later on, you're correctly getting the TableItem text:
table.getItem(playerIndices[0]).getText();
So instead of using the toString() method on those two lines at the start, you'll want to use getText() as you've done here.
I am looking to get the value of the selected row in an AbstractTableModel and I am noticing some things. It is correctly reporting what sell (row) I am on, when it is selected, but as soon as I click my button to remove, the selected row value goes to 0. Resulting in the 0 row always being removed. I want to get the value int selectedRow and use it to remove it from the table and my ArrayLists.
ListSelectionModel rsm = table.getSelectionModel();
ListSelectionModel csm = table.getColumnModel().getSelectionModel();
csm.addListSelectionListener(new SelectionDebugger(columnCounter,csm));
columnCounter = new JLabel("(Selected Column Indices Go Here)");
columnCounter.setBounds(133, 62, 214, 14);
csm.addListSelectionListener(new SelectionDebugger(columnCounter,csm));
contentPane1.add(columnCounter);
rowCounter = new JLabel("(Selected Column Indices Go Here)");
rowCounter.setBounds(133, 36, 214, 14);
rsm.addListSelectionListener(new SelectionDebugger(rowCounter, rsm));
contentPane1.add(rowCounter);
SelectionDebugger:
public class SelectionDebugger implements ListSelectionListener {
JLabel debugger;
ListSelectionModel model;
public SelectionDebugger(JLabel target, ListSelectionModel lsm) {
debugger = target;
model = lsm;
}
public void valueChanged(ListSelectionEvent lse) {
if (!lse.getValueIsAdjusting()) {
// skip all the intermediate events . . .
StringBuffer buf = new StringBuffer();
int[] selection = getSelectedIndices(model.getMinSelectionIndex(),
model.getMaxSelectionIndex());
if (selection.length == 0) {
buf.append("none");
//selectedRow = buf.toString();
}
else {
for (int i = 0; i < selection.length -1; i++) {
buf.append(selection[i]);
buf.append(", ");
}
buf.append(selection[selection.length - 1]);
}
debugger.setText(buf.toString());
System.out.println("CampaignConfiguration: Selected Row: " + selection[selection.length - 1]);
// Set the selected row for removal;
selectedRow = selection[selection.length - 1];
}
}
// This method returns an array of selected indices. It's guaranteed to
// return a nonnull value.
protected int[] getSelectedIndices(int start, int stop) {
if ((start == -1) || (stop == -1)) {
// no selection, so return an empty array
return new int[0];
}
int guesses[] = new int[stop - start + 1];
int index = 0;
// manually walk through these . . .
for (int i = start; i <= stop; i++) {
if (model.isSelectedIndex(i)) {
guesses[index++] = i;
}
}
// ok, pare down the guess array to the real thing
int realthing[] = new int[index];
System.arraycopy(guesses, 0, realthing, 0, index);
return realthing;
}
}
}
The TableModel has nothing to do with selection. The View(JTable) is responsible for the selection.
I want to get the value int selectedRow and use it to remove it from the table and my ArrayLists.
You should NOT have separate ArrayLists. The data should only be contained in the TableModel.
If you want to delete a row from the table (and the TableModel) then you can use the getSelectedIndex() method of the table in your ActionListener added to the "Delete" button. Something like:
int row = table.getSelectedIndex();
if (row != -1)
{
int modelRow = table.convertRowIndexToModel( row );
tableModel.removeRow( modelRow );
}
If you are not using the DefaultTableModel, then your custom TableModel will need to implement the "removeRow(...)" method.