Windows resize while dragging - javafx-2

My application is an Horizontal Flow SplitPane in an AnchorPane. On the right side of the SplitPane I can plot windows by left click on a button.
I can also arrange these windows horizontally or vertically to fit the parent container prefSize, and it all works fine.
My issue is about how to auto-resize windows when I resize the GUI because if I click and drag on the rightmost pane I get this effect.
So, my question is: how to bind the windows to autoresize itself when narrow or widen the GUI?
Thanks all
Edit: here is how I arrange windows vertically
#FXML
private void windowsArrangeVertically(ActionEvent event) {
// tutto il contenuto del tab, compreso il gruppo
Group gp = (Group) tabpaneWorkspace.getSelectionModel().getSelectedItem().getContent();
int itemsInTab = gp.getChildren().size();// dimensione del contenuto del tab, gruppo compreso
int totWindows = 0;
Window winItem;
// voglio sapere quante sono le window presente nel tab, escludendo il gruppo
for(int i=0; i<itemsInTab; i++){
if(gp.getChildren().get(i) instanceof Window){
totWindows++;
}
}
// mi serve per riposizionare le finestre sulle x
double x = 0;
for(int i=0; i<itemsInTab; i++){
// se il contenuto del tab è un istanza di window
if(gp.getChildren().get(i) instanceof Window){
// allora scorri tutto il contenuto uno per uno
winItem = (Window)gp.getChildren().get(i);
// determina la larghezza della finestra in base al num di windows presenti
double tabWidth = tabpaneWorkspace.getWidth()/totWindows;
// e assegna la larghezza
winItem.setPrefSize(tabWidth , tabpaneWorkspace.getHeight()-31);
winItem.setLayoutX(x);
winItem.setLayoutY(0);
x += tabWidth;
}
};
}

Related

Using binomal distribution with Spark to calculate an expected value and a variance ("number of times getting a six when throwing a dice three times")

I'm training myself to resolve classical statistics exercices with Spark and it's MLib module when needed, in order to face any situation later.
Spark is dedicated to calculation on matrices, but let's say that I have a side calculation to do in my program, at a time, and that I would like to resolve it with Spark, without adding others APIs.
The calculation is simple : learn the expected value and the variance
of having a six on a dice, when you throw it three times.
Currently, I resolve it by the help of the Apache maths API and a bit of Spark :
/** Among imports : */
import org.apache.commons.math3.distribution.*;
/**
* E8.5 : On lance trois dés. Probabilité d'un six obtenu ?
* Suit une loi binomiale B(3, 1/6)
* Par calcul : F(0) = 125/216, F(1) = 125/216 + 75/216, F(2) = (125 + 75 + 15)/216,
* F(3) = (125 + 75 + 15 + 1)/216 = 1
*/
#Test
#DisplayName("On lance trois dés. Probabilité d'un six obtenu ?. Caractéristiques de la loi B(3, 1/6)")
public void troisDésDonnentUnSix() {
int n = 3; // Nombre de lancés de dés.
double v[] = {0, 1, 2, 3}; // Valeurs possibles de la variable aléatoire.
double f[] = new double[n+1]; // Fréquences cumulées.
double p[] = new double[n+1]; // Probabilités.
// Calculer les probabilités et les fréquences.
BinomialDistribution loiBinomale = new BinomialDistribution(n, 1.0/6.0);
for(int i=0; i <= n; i++) {
p[i] = loiBinomale.probability(i);
f[i] = loiBinomale.cumulativeProbability(i);
}
LOGGER.info("P(x) = {}", p);
LOGGER.info("F(x) = {}", f);
Dataset<Row> ds = fromDouble(v, p);
LOGGER.info("E(X) = {}, V(X) = {}", esperance(ds), variance(ds));
}
where fromDouble(v, p) method creates a Dataset from a list of random variable values (column x) and their associated frequencies (column Px) :
/**
* Renvoyer un Dataset depuis une série de valeurs entières à probabilités.
* #param valeurs Valeurs.
* #param probabilites Probabilités.
* #return Dataset avec une colonne x, entière, contenant les valeurs<br>
* et une colonne Px, décimale, contenant les probabilités.
*/
protected Dataset<Row> fromDouble(double[] valeurs, double[] probabilites) {
StructType schema = new StructType()
.add("x", DoubleType, false)
.add("Px", DoubleType, false);
List<Row> rows = new ArrayList<>();
for(int index=0; index < valeurs.length; index ++) {
rows.add(RowFactory.create(valeurs[index], probabilites[index]));
}
return this.session.createDataFrame(rows, schema);
}
And esperance (= expected value) and variance methods called are doing these calculations :
/**
* Calculer l'espérance sur un Dataset avec valeurs et probabilités.
* #param ds Dataset avec colonnes : <br>
* x : valeur<br>
* Px : fréquence<br>
* #return espérance.
*/
protected double esperance(Dataset<Row> ds) {
return ds.agg(sum(col("x").multiply(col("Px")))).first().getDouble(0);
}
/**
* Calculer la variance sur un Dataset avec valeurs et probabilités.
* #param ds Dataset avec colonnes : <br>
* x : valeur<br>
* Px : fréquence<br>
* #return espérance.
*/
protected double variance(Dataset<Row> ds) {
Column variation = col("x").minus(esperance(ds));
Column variationCarre = variation.multiply(variation);
Column termeCalculVariance = col("Px").multiply(variationCarre);
return ds.agg(sum(termeCalculVariance)).first().getDouble(0);
}
LOGGER output :
P(x) = [0.5787037037037037, 0.34722222222222215, 0.06944444444444445, 0.0046296296296296285]
F(x) = [0.5787037037037035, 0.9259259259259259, 0.9953703703703703, 1.0]
E(X) = 0.49999999999999994, V(X) = 0.41666666666666663
It works (? I have caculatd by hand "E(X) = 53/108", and it finds 54/108 = 0.5..., I might be wrong), but it's not perfect.
Is there a more elegant way to solve this problem using Spark (and Spark-MLib, if needed) ?

Converting client coordinates to Pixel coordinates for simulating a mouse click in MFC

I am trying to simulate a mouse click on the CView window in a legacy code which I must say I don't fully understand. The idea is to search for a particular item in the CView, get its co-ordinates and then simulate a right mouse click on it using SendInput. I want to understand if the basic steps I am following are correct before I proceed digging further into the legacy code which has a bunch of transformations happening across co-ordinate systems :( Here are the steps I follow:
Get the position co-ordinates of the item displayed in CView. at this point the co-ordinates is in the internal co-ordinate system (lets call it CDPoint).
CDPoint gPosn = viewObj->m_point_a ;
Covert the co-ordinates to the client co-ordinate system i.e CDPoint to CPoint using the existing transformations in the code.
CPoint newPosn = GetTransform().Scale(gPosn);
//Note: The basis of arriving that this is the correct transformation to use is the below code with the exact reverse transform happening in the mouse click handler code to convert CPoint to CDPoint:
`CDesignView::OnLButtonDown(UINT nFlags, CPoint p) {
CDPoint np = GetTransform().DeScale(p);
}`
Is this thinking right that CPoint received in the OnLButtonDown() handler will always be in the client co-ordinates and hence the reverse transform should convert CDPoint (internal co-ordinates) to client coordinates (CPoint) ?
Convert client co-ordinates to screen co-ordinates:
ClientToScreen(&newPosn);
Pass these values to SendInput function after converting to pixel co-ordinates:
INPUT buffer[1];
MouseSetup(buffer);
MouseMoveAbsolute(buffer, newPos.x, newPos.y);
MouseClick(buffer);
The Mousexxx() functions are defined as below similar to the sample code in this post:
How to simulate a mouse movement
.
#define SCREEN_WIDTH (::GetSystemMetrics( SM_CXSCREEN )-1)
#define SCREEN_HEIGHT (::GetSystemMetrics( SM_CYSCREEN )-1)
static void inline makeAbsXY(double &x, double &y) {
x = (x * 0xFFFF) / SCREEN_WIDTH ;
y = (y * 0xFFFF) / SCREEN_HEIGHT ;
}
static void inline MouseSetup(INPUT *buffer)
{
buffer->type = INPUT_MOUSE;
buffer->mi.dx = (0 * (0xFFFF / SCREEN_WIDTH));
buffer->mi.dy = (0 * (0xFFFF / SCREEN_HEIGHT));
buffer->mi.mouseData = 0;
buffer->mi.dwFlags = MOUSEEVENTF_ABSOLUTE;
buffer->mi.time = 0;
buffer->mi.dwExtraInfo = 0;
}
static void inline MouseMoveAbsolute(INPUT *buffer, double x, double y)
{
makeAbsXY(x,y) ;
buffer->mi.dx = x ;
buffer->mi.dy = y ;
buffer->mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE);
SendInput(1, buffer, sizeof(INPUT));
}
static void inline MouseClick(INPUT *buffer)
{
buffer->mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_RIGHTDOWN);
SendInput(1, buffer, sizeof(INPUT));
Sleep(10);
buffer->mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_RIGHTUP);
SendInput(1, buffer, sizeof(INPUT));
}
Could anyone pls provide pointers on what might be going wrong in these steps since the simulated mosue click always seem to be shifted left by some factor which keeps increasing as x becoems larger. I have verified that is gPosn is pointing to (0,0) it always simulates a mouse click on the top right corner of the client screen.
Thanks for your time.
If you have x and y in client coordinates, you have to convert them to screen coordinates:
POINT point;
point.x = x;
point.y = y;
::ClientToScreen(m_hWnd, point);
Where m_hWnd is the window which owns the objects. x and y are relative to top-left of the client area of this window.
Assuming point.x and point.y are in screen coordinates, the rest of the conversion for SendInput is correct. You can also create INPUT array for SendInput, this will send the mouse messages without interruption.
INPUT input[3];
for (int i = 0; i < 3; i++)
{
memset(&input[i], 0, sizeof(INPUT));
input[i].type = INPUT_MOUSE;
}
input[0].mi.dx = (point.x * 0xFFFF) / (GetSystemMetrics(SM_CXSCREEN) - 1);
input[0].mi.dy = (point.y * 0xFFFF) / (GetSystemMetrics(SM_CYSCREEN) - 1);
input[0].mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
input[1].mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
input[2].mi.dwFlags = MOUSEEVENTF_RIGHTUP;
SendInput(3, input, sizeof(INPUT));

How increment ++ really works and how to adapt it to exclude an invalidity?

The context:
As part of a class project, I created this code (Original Version). It works great, had almost full grade. As I was learning new materials, I challenge myself to rewrite the original code and to implement the new stuff in it. So basically what this new version (not much difference with the original - feel free to compare) does is:
you enter a letter c/C for circle, r/R for rectangle, and k/K for Square,
enter the desire measurement,
it accordingly calculates the perimeter and the surface,
as the user if he wants to continue,
repeat the process,
display (in same order) the following information when the user decides to stop:
total number of figures treated,
the larger surface,
the smaller circle perimeter,
total number of rectangle with length > 7.8,
total number of square treated,
the average length of the side of the square treated.
Notice in the execution below that 3 of the 4 characters enter are valid. So we get their surface and perimeter. However 'T' is an invalid character, but when the user decides not to continue it is still counted as part of the total figure and gives me 4 instead of 3:
Entrez le caractere correspondant a la figure geometrique (c,C,r,R,k,K): c
Veuillez entrer le rayon: 10
Le perimetre est de: 62.83
La surface est de: 314.16
Voulez-vous continuer ? (o/n) o
Entrez le caractere correspondant a la figure geometrique (c,C,r,R,k,K): t
Le caractere 'T' est invalide
Voulez-vous continuer ? (o/n) o
Entrez le caractere correspondant a la figure geometrique (c,C,r,R,k,K): k
Veuillez entrer le cote du carre: 5
Le perimetre est de: 20.00
La surface est de: 25.00
Voulez-vous continuer ? (o/n) o
Entrez le caractere correspondant a la figure geometrique (c,C,r,R,k,K): r
Veuillez entrer la longeur et largeur du rectangle: 10 5
Le perimetre est de: 30.00
La surface est de: 50.00
Voulez-vous continuer ? (o/n) n
Au total, on a traite 4 figure(s)
La surface la plus grande est: 314.16
Il y a 1 rectangle(s) dont la longueur depasse 7.80 metres
Le plus petit perimetre des cercles est: 62.83
Le nombre total de carre traitees : 1
Le cote moyen des carres traites est de: 5.00
Process returned 0 (0x0) execution time : 47.514 s
Press any key to continue.
Question:
How to adapt the increment (somFigure++) in a way that it only counts the valid characters enter by the user?
Source code:
int main() {
char figure,
reponse;
int valide,
nbCarre = 0,
somFigure = 0,
nbGrRec = 0;
float perimetre,
surface,
rayon,
longueur,
largeur,
cote,
somCarre = 0.0,
plusGrandeSurface = 0.0,
plusPetitPerimetreC = 5000.0;
const float PI = 3.14159,
GRAND_RECTANGLE = 7.8;
do
{
printf("Entrez le caractere correspondant a la figure geometrique (c,C,r,R,k,K): ");
fflush(stdin);
figure = toupper(getchar());
valide = (figure == 'C') || (figure == 'R') || (figure == 'K');
somFigure++;
switch (figure) {
case 'C': printf("Veuillez entrer le rayon: ");
scanf("%f", &rayon);
perimetre = 2 * PI * rayon;
surface = PI * rayon * rayon;
if (surface > plusGrandeSurface)
plusGrandeSurface = surface;
if (perimetre < plusPetitPerimetreC)
plusPetitPerimetreC = perimetre;
break;
case 'R': printf("Veuillez entrer la longeur et largeur du rectangle: ");
scanf("%f%f", &longueur, &largeur);
perimetre = 2 * (longueur + largeur);
surface = longueur * largeur;
if (longueur > GRAND_RECTANGLE)
nbGrRec++;
if (surface > plusGrandeSurface)
plusGrandeSurface = surface;
break;
case 'K': printf("Veuillez entrer le cote du carre: ");
scanf("%f", &cote);
perimetre = 4 * cote;
surface = cote * cote;
nbCarre++;
somCarre += cote;
if (surface > plusGrandeSurface)
plusGrandeSurface = surface;
break;
default: printf("Le caractere '%c' est invalide\n", figure);
} /* Fin du Switch */
if (valide)
printf("Le perimetre est de: %.2f\n", perimetre),
printf("La surface est de: %.2f\n", surface);
printf("\nVoulez-vous continuer ? (o/n) ");
fflush(stdin);
reponse = getchar();
fflush(stdin);
}while(toupper(reponse) == 'O'); /* Fin de la boucle do....while */
printf("\nAu total, on a traite %d figure(s)\n", somFigure);
printf("La surface la plus grande est: %.2f\n", plusGrandeSurface);
if (nbGrRec > 0)
{
printf("Il y a %d rectangle(s) dont la longueur depasse %.2f metres\n", nbGrRec, GRAND_RECTANGLE);
}
else
printf("Il y a aucun rectangle traite\n");
if (plusPetitPerimetreC != 5000.0)
{
printf("Le plus petit perimetre des cercles est: %.2f\n", plusPetitPerimetreC);
}
else
printf("Il y a aucun cercle traite\n");
// Fait un resumer des nombre de carrés traités si l'utilisateur decise de ne plus continuer
if (nbCarre > 0)
{
printf("Le nombre total de carre traitees : %d\n", nbCarre);
printf("Le cote moyen des carres traites est de: %.2f\n", somCarre / nbCarre);
}
else
printf("Il y a aucun carre traite\n");
return 0;
}
You can do this:
if (valide) {
somFigure++;
printf("Le perimetre est de: %.2f\n", perimetre),
printf("La surface est de: %.2f\n", surface);
}
Also note that the original code without the curly braces probably does not work as you expect. The first printfstatement will be executed only if valide is true but the second one will be executed in any case. It's a good practice to always use curly braces with if statements to avoid errors like this.

vaadin table vertically till but not beyond the bottom of the page, scrollbars as needed

In my vaadin 7 application I have a CSSLayout that contains a Tabsheet. The Tabsheet contains a horizontalLayout. The HorizontalLayout contains a Table.
The table have a varying number of columns (between 3 and 20, changes upon request).
I want this table to occupy all available space both horizontally and vertically.
Vertically however the table should not extend beyond the the screen. So in case of having more rows than it can display the table should have a vertical scrollbar. (That is the case if I set the number of rows in table.setPageLength(), however I want to achieve this without setting explicit rownumbers, because I want the table to occupy all available space regardless of screensize, etc...)
Horizontally I also want a scrollbar if there are more columns then we have space for.
If I leave everything (csslayout, tabsheet, horizontallayout, table) default, I get the scrollbars, but I get a lot of space unused.
If I use setSizeFull() on tabsheet, horizontallayout, table then I get no unused space, however I lose the horizontal scrollbar and I can't ever reach end of the table with the vertical scrollbar.
Any help is appreciated.
EDIT -- UPDATE -- EDIT -- UPDATE --EDIT -- UPDATE --EDIT -- UPDATE
Here is a sample code. On my screen it's impossible to scroll down to the last row of the table. (and equally impossible to use the horizontal scrollbar)
#Override
protected void init(#SuppressWarnings("unused") VaadinRequest request) {
CssLayout css = new CssLayout();
HorizontalLayout upper = new HorizontalLayout();
OptionGroup first = new OptionGroup();
first.addItem("AAA");
first.addItem("BBB");
first.addItem("CCC");
first.addItem("DDD");
first.addItem("EEE");
first.addItem("Whatever");
upper.addComponent(first);
css.addComponent(upper);
HorizontalLayout hl = new HorizontalLayout();
hl.setMargin(true);
hl.setSpacing(true);
IndexedContainer c = new IndexedContainer();
for (int i = 0; i < 40; i++)
c.addContainerProperty("name" + i, String.class, "name" + i);
Table table = new Table("Test table", c);
for (int i = 0; i < 100; i++) {
Integer id = (Integer) c.addItem();
c.getItem(id).getItemProperty("name0").setValue(String.valueOf(i));
}
hl.addComponent(table);
TabSheet tab = new TabSheet();
tab.addTab(hl, "Table");
css.addComponent(tab);
hl.setSizeFull();
table.setSizeFull();
tab.setSizeFull();
css.setSizeFull();
setContent(css);
}
Maybe you don't set the size full on the css layout or maybe there are some trouble with styles.
It's better posting some code in questions like Why my code dosen't work?. However I wrote a simple test following your description and work as expected.
Edit
Try with VerticalLayout instead CssLayout
public class TestTableApp extends UI {
#Override
protected void init(VaadinRequest request) {
VerticalLayout css = new VerticalLayout();
HorizontalLayout upper = new HorizontalLayout();
OptionGroup first = new OptionGroup();
first.addItem("AAA");
first.addItem("BBB");
first.addItem("CCC");
first.addItem("DDD");
first.addItem("EEE");
first.addItem("Whatever");
upper.addComponent(first);
css.addComponent(upper);
HorizontalLayout hl = new HorizontalLayout();
hl.setMargin(true);
hl.setSpacing(true);
IndexedContainer c = new IndexedContainer();
for (int i = 0; i < 40; i++)
c.addContainerProperty("name" + i, String.class, "name" + i);
Table table = new Table("Test table", c);
for (int i = 0; i < 100; i++) {
Integer id = (Integer) c.addItem();
c.getItem(id).getItemProperty("name0").setValue(String.valueOf(i));
}
hl.addComponent(table);
TabSheet tab = new TabSheet();
tab.addTab(hl, "Table");
css.addComponent(tab);
hl.setSizeFull();
tab.setSizeFull();
table.setSizeFull();
css.setSizeFull();
// this do the trick
css.setExpandRatio(upper, 0);
css.setExpandRatio(tab, 1);
setContent(css);
}
}

How to use the repaint method

I am trying to use the repaint method in the following code to update the screen after user input. The game is a card game where the user has to click on two cards to reveal their pictures. If the pictures match the cards remain visible however if the pictures don't match the cards flip over to hide the pictures once again.
The first card becomes visible after clicking it, however when the second card is selected either both cards become visible if a matching picture is selected or the first card just flips over without the second picture being revealed.
Thanks for your help.
addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e) {
int row = e.getX() / (Card.SIZE*2);
int col = e.getY() / (Card.SIZE*3);
//OPEN means the picture is visible
if(cards[row][col].getState() == Card.CLOSED)
cards[row][col].setState(OPEN);
repaint();
compareCards(row,col);
}
});
}
public void compareCards(int row, int col){
if(clickNum == 1){
r1 = row;
c1 = col;
clickNum++;
}
else if(clickNum == 2){
r2 = row;
c2 = col;
//The OR accounts for clicking twice on the same tile
if(cards[r1][c1].getNum() != cards[r2][c2].getNum() || (r1 == r2 && c1 == c2)){
cards[r1][c1].setState(CLOSED);
cards[r2][c2].setState(CLOSED);
}
clickNum = 1;
}
}
Your compare cards function is setting the card states to CLOSED much too quickly, and so they are not displaying. Try using:
public void compareCards(int row, int col){
try
{
Thread.sleep(5000);//sleep for five seconds
}catch(Exception e){}
if(clickNum == 1){
r1 = row;
c1 = col;
clickNum++;
}
else if(clickNum == 2){
r2 = row;
c2 = col;
//The OR accounts for clicking twice on the same tile
if(cards[r1][c1].getNum() != cards[r2][c2].getNum() || (r1 == r2 && c1 == c2)){
cards[r1][c1].setState(CLOSED);
cards[r2][c2].setState(CLOSED);
}
clickNum = 1;
}
}
This should display both cards for about five seconds before turning them over. You'll also have to implement a method which handles flipping the cards back over if they are the same if you don't already have one. I only say this because I don't see one here.

Resources