Default javafx tableview scroll bar position - scrollbar

I am having tableview at my .fxml file like below,
<TableView fx:id="tblViewer" prefHeight="340.0" prefWidth="800.0"
styleClass="tableview" stylesheets="#ClsMain.css" />
I have select box of tables. When I am selecting any table all the data with columns populated into tableview. If columns are more, than tableview automatically render the horizontal scroll bar to it same for vertical scroll bar.
Problem is when I scroll to right end and if I am changing the dropdown selection it is not let me go to the left side. And some of the columns are truncated from the left. Like showing in the image.
If you have the solution then help me out please.
Kind Regards.
Updated:
Here I am binding the tableview and the data
private void initClsTable() {
System.out.println("in inintClsTable");
Bindings.bindContentBidirectional(tblViewer.getColumns(), getViewModel().getColumnList());
Bindings.bindContentBidirectional(tblViewer.getItems(), getViewModel().getDataList());
}
Here my selection taken place: (When user changes the selection)
private void subscribechoosenTableDataConfig() {
this.columnsList.clear();
this.dataList.clear();
System.out.println("subscribechoosenTableDataConfig");
if (choosenTableDataConfig.get() != null && choosenTableDataConfig.getValue().getTableName() != null
&& choosenTableDataConfig.getValue().getTableNumber() != 0) {
clsManager.tell(new ClsManager.ClsTableDataRequest(eventHandler, choosenTableDataConfig.getValue()
.getTableName(), choosenTableDataConfig.getValue().getTableNumber()), ActorRef.noSender());
}
}

By removing these two lines I have what I wanted.
this.columnsList.clear();
this.dataList.clear();
Many thanks to ItachiUchiha

Related

How to replace down arrow with text in a combobox in JavaFX

I'm trying to remove the down arrow from a combobox. All the solutions I have found just make the arrow disappear, for example this one.
Is there a way to remove completely the space where the arrow appears and fill the box just with the text of the selected choice?
If you want to completely elimnate the arrow & arrow button space, you can try with the below custom ComboBox.
The below code is setting the arrow button and arrow nodes size to 0 and asking to rerender the comboBox. The null check is to let this changes apply only once.
public class MyComboBox<T> extends ComboBox<T>{
Region arrowBtn ;
#Override
protected void layoutChildren() {
super.layoutChildren();
if(arrowBtn==null){
arrowBtn= (Region)lookup(".arrow-button");
arrowBtn.setMaxSize(0,0);
arrowBtn.setMinSize(0,0);
arrowBtn.setPadding(new Insets(0));
Region arrow= (Region)lookup(".arrow");
arrow.setMaxSize(0,0);
arrow.setMinSize(0,0);
arrow.setPadding(new Insets(0));
// Call again the super method to relayout with the new bounds.
super.layoutChildren();
}
}
}
UPDATE :
Based on the suggestion of #kleopatra, we can get the same behaviour using css as well (without the need to create a new class for ComboBox).
.combo-box .arrow-button,
.combo-box .arrow{
-fx-max-width:0px;
-fx-min-width:0px;
-fx-padding:0px;
}
The below image will tell you the difference of a normal combox box and this custom combo box. The left one is the normal comboBox, you can see the list cell when inspecting with ScenicView. The right one is the custom one. The list cell is completely occupied suppressing the arrow space.

Gluon ScrollPane refresh issue

I have a messaging application running in Android which has the setup like in setup of the screen
the order is as below
<View>
<BorderPane>
<center>
<ScrollPane>
<content>
<VBox> //issue is here
</content>
<ScrollPane>
<center>
<bottom>
<TextField>
<bottom>
</BorderPane>
</View>
When I add children to VBox with
VBox.getChildren().add(TextLabel);
The ScrollPane gets new VBox and shows that on the screen.
However when i add more children that what current screen can fit i scroll to end of the ScrollPane by setting vvalueProperty();
ScrollPane.vvalueProperty().bind(VBox.heightProperty());
(Above code is essential to recreate the issue)
This works perfectly fine when running it on computer but on mobile i have this weird issue where scrollPane drops VBox when i add more children than what can be fit on the screen. And when i click on the VBox area the screen refreshes and i get the desired content on the screen
Video demonstrating ScrollBar issue in gluon
For convenience i have set following color code
ScrollBar - Red
VBox - Blue
As an alternative to binding I also tried
ScrollBar.setVvalue(1.0);
setVvalue() did not have same issue but this on the other hand was not showing the last message in the view.
Right now i have tried all possible combinations including replacing VBox with FlowPane and observed same behavior.
I can reproduce your issue on an Android device. Somehow, as discussed in the comments above, the binding of the vertical scroll position is causing some race condition.
Instead of trying to find out the cause of that issue, I'd rather remove the binding and propose a different approach to get the desired result: the binding is a very strong condition in this case.
When you try to do in the same pass this:
vBox.getChildren().add(label);
scrollPane.setVvalue(vBox.getHeight());
you already noticed and mentioned that the scroll position wasn't properly updated and you were missing the last item added to the vBox.
This can be explained easily: when you add a new item to the box, there is a call to layoutChildren() that will take some time to be performed. At least it will take another pulse to get the correct value.
But since you try to set immediately the vertical scroll position, the value vBox.getHeight() will still return the old value. In other words, you have to wait a little bit to get the new value.
There are several ways to do it. The most straightforward is with a listener to the box's height property:
vBox.heightProperty().addListener((obs, ov, nv) ->
scrollPane.setVvalue(nv.doubleValue()));
As an alternative, after adding the item to the box, you could use:
vBox.getChildren().add(label);
Platform.runLater(() -> scrollPane.setVvalue(vBox.getHeight()));
But this doesn't guarantee that the call won't be done immediately. So it is better to do a PauseTransition instead, where you can control the timing:
vBox.getChildren().add(label);
PauseTransition pause = new PauseTransition(Duration.millis(30));
pause.setOnFinished(f -> scrollPane.setVvalue(vBox.getHeight()));
pause.play();
As a suggestion, you could also do a nice transition to slide in the new item.
Alternative solution
So far, you are using an ScrollPane combined with a VBox to add a number of items, allowing scrolling to the first item on the list but keeping the scroll position always at the bottom so the last item added is fully visible. While this works fine (with my proposal above to avoid the binding), you are adding many nodes to a non virtualized container.
I think there is a better alternative, with a ListView (or better a CharmListView that will allow headers). With the proper CellFactory you can have exactly the same visuals, and you can directly scroll to the last item. But the main advantage of this control is its virtualFlow, that will manage for you a limited number of nodes while you have many more items added to a list.
This is just a short code snippet to use a ListView control for your chat application:
ListView<String> listView = new ListView<>();
listView.setCellFactory(p -> new ListCell<String>() {
private final Label label;
{
label = new Label(null, MaterialDesignIcon.CHAT_BUBBLE.graphic());
label.setMaxWidth(Double.MAX_VALUE);
label.setPrefWidth(this.getWidth() - 60);
label.setPrefHeight(30);
}
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item != null && ! empty) {
label.setText(item);
label.setAlignment(getIndex() % 2 == 0 ? Pos.CENTER_LEFT : Pos.CENTER_RIGHT);
setGraphic(label);
} else {
setGraphic(null);
}
}
});
setCenter(listView);
and to add a new item and scroll to it, you just need:
listView.getItems().add("Text " + (listView.getItems().size() + 1));
listView.scrollTo(listView.getItems().size() - 1);
Of course, with the proper styling you can remove the lines between rows, and create the same visuals as with the scrollPane.

How to keep an item view scrolled to the bottom when items are added?

When appending items at the end of a model shown by a QAbstractItemView, I wish to keep the view at the bottom of the data, showing the most recent added items. The default behavior is to retain the most recently displayed item's position, but not to scroll if we were at the bottom.
What would be the magic needed to keep the view at the bottom if the user has previously scrolled it all the way to the bottom?
QListView view;
bool viewAtBottom = false;
Before an item is added, check if the view is scrolled all the way to the bottom.
connect(view.model(), &QAbstractItemModel::rowsAboutToBeInserted,
&view, [&] {
auto bar = view.verticalScrollBar();
viewAtBottom = bar ? (bar->value() == bar->maximum()) : false;
});
After an item is inserted, scroll to the bottom if the view was previously at the bottom before the item got added.
connect(view.model(), &QAbstractItemModel::rowsInserted,
&view, [&]{ if (viewAtBottom) view.scrollToBottom(); });

Select QGraphicsItem

I have problems selecting my QGraphicsItem.
I have multiple Items (Line and Ellipse) and Itemgroups (containing lines).
In some cases they are overlaying each other but are still visible because of transparency.
For example: I first create a small circle and later i create a bigger circle around the small one.
How can I select the small circle?
I only want an item beeing selected if i click on a visible nontransparent part of it (maybe with some tolerance for lines of 1px width). How can I do that?
A small example how i create a circle:
circleToDraw = new QGraphicsEllipseItem;
this->addItem(circleToDraw);
circleToDraw->setPen(QPen(Qt::black, 1, Qt::SolidLine));
circleToDraw->setPos(origPoint);
circleToDraw->setRect(origPoint.y() - event->scenePos().y(), origPoint.y() - event->scenePos().y(), (event->scenePos().y() - origPoint.y())*2, (event->scenePos().y() - origPoint.y())*2);
Later i will also implement some QImages with transparent parts. Here the problem will be again, that I want to select Items under the transparent part.
Thank you!
Edit
My code for now:
QList<QGraphicsItem *> items = this->items(event->scenePos());
for each(QGraphicsItem* item in items)
{
if(item->opacity() == 1){
//opacity() does not work as expected
//circle will still be deleted when I click the (transparent) inside of it
//item->setSelected(true); //selects all items while pressing mouse, but only top item after releasing mouse. why?
this->removeItem(item);
delete(item);
}
}

show border on rollover and select the thumb on click and unselect pre selected thumb

I have some small canvas, and i have to show border around them, i did that using rollover and rollout evenets, (these canvas hold product images), here rollover and rollout are working perfectly fine, but when a user clicks on some canvas, it has to be selected, means it has show the border around it, and rest canvas should work as normal. but when i select another canvas the previously selected canvas should get unselected and new clicked canvas gets the selection,
but the problem which is coming the rollOut event which is applied on canvas, on a click the canvas get selected, but when rollOut takes place it unselect the canvas, i even removed the rollOut listner on the click of a canvas, but in that case, the clicked canvas will not get unselected , when other canvas will be clicked
can.addEventListener(MouseEvent.ROLL_OVER,onRollOverThumb);
can.addEventListener(MouseEvent.ROLL_OUT,onRollOutThumb);
//can.addEventListener(MouseEvent.CLICK,onRollOverThumb);
private function onRollOverThumb(event:MouseEvent):void
{
event.target.setStyle('borderColor','0x000000');
event.target.setStyle('borderThickness','3');
event.target.setStyle('borderStyle','solid');
}
private function onRollOutThumb(event:MouseEvent):void
{
event.target.setStyle('borderColor','0xCCCCCC');
event.target.setStyle('borderThickness','1');
event.target.setStyle('borderStyle','solid');
}
i hope some thing are clear in this, does n e one has worked on this, please reply
Thanks in advance
Ankur sharma
What about implementing a "flag" variable that is set to true when the click occurs. Then, when the ROLL_OUT occurs, check if the flag is true or false. If true, don't do anything, if false, remove/change the border.
private function onRollOverThumb(event:MouseEvent):void
{
if(event.type=='click')
{
for(var j:int=0;j<viewparent.numChildren;j++)
{
viewparent.getChildAt(j).name="false";
}
event.currentTarget.name="true";
for(var i:int=0;i<viewparent.numChildren;i++)
{
if(viewparent.getChildAt(i).name=="true")
{
Canvas(viewparent.getChildAt(i)).setStyle('borderColor','0x000000');
Canvas(viewparent.getChildAt(i)).setStyle('borderThickness','3');
Canvas(viewparent.getChildAt(i)).setStyle('borderStyle','solid');
}
else
{
Canvas(viewparent.getChildAt(i)).setStyle('borderColor','0xCCCCCC');
Canvas(viewparent.getChildAt(i)).setStyle('borderThickness','1');
Canvas(viewparent.getChildAt(i)).setStyle('borderStyle','solid');
}
}
}
else
{
event.currentTarget.setStyle('borderColor','0x000000');
event.currentTarget.setStyle('borderThickness','3');
event.currentTarget.setStyle('borderStyle','solid');
}
}
private function onRollOutThumb(event:MouseEvent):void
{
if(event.currentTarget.name=="false")
{
event.currentTarget.setStyle('borderColor','0xCCCCCC');
event.currentTarget.setStyle('borderThickness','1');
event.currentTarget.setStyle('borderStyle','solid');
}
}
i modified my own code, added one name property to the canvases
can.name="false"
and it's now working,
can n e one tell me, how to put some select and unselect(kind of fade effect) on the border, when the black selection get removed, it shld be removed in some fade manner, can we apply fade effect on border?

Resources