#java #javafx #layout
#java #javafx #макет
Вопрос:
Я бы хотел, чтобы вертикальная отметка времени следовала за курсором мыши по нескольким хронограммам, чтобы указать отметку времени, но setLayoutX() или relocate() вообще не влияют на StackPane.
Я написал следующий минимально воспроизводимый пример:
public class VerticalTimeMarkIsNotRelocated extends Application {
@FXML private StackPane timeMarkContainer;
@FXML private Label label;
@FXML private VBox timeMark;
@FXML
private void initialize() {
StackPane.clearConstraints( timeMark );
StackPane.setAlignment( label, Pos.BOTTOM_CENTER );
}
@FXML
private void moveTimeMark( MouseEvent e ) {
final double x = e.getX();
System.err.printf( "%7.2fn", x );
timeMark.relocate( x, 0 );
}
@Override
public void start( Stage primaryStage ) throws Exception {
final Class<?> clazz = getClass();
primaryStage.setScene( new Scene( FXMLLoader.load( clazz.getResource( clazz.getSimpleName() ".fxml" ))));
primaryStage.show();
}
public static void main( String[] args ) {
launch( args );
}
}
VerticalTimeMarkIsNotRelocated.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.net.URL?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<StackPane xmlns:fx="http://javafx.com/fxml" fx:controller="so.VerticalTimeMarkIsNotRelocated"
fx:id="timeMarkContainer" prefWidth="420" prefHeight="140" onMouseMoved="#moveTimeMark">
<stylesheets>
<URL value="@VerticalTimeMarkIsNotRelocated.css" />
</stylesheets>
<Label fx:id="label" text="Replacement for several chronogram widgets" />
<VBox fx:id="timeMark" minWidth="1.0" maxWidth="1.0" />
</StackPane>
VerticalTimeMarkIsNotRelocated.css:
#timeMark {
-fx-background-color: red;
}
#label {
-fx-background-color: bisque;
-fx-padding: 40px;
}
На следующем снимке экрана в консоли Eclipse мы видим, что мышь перемещается, но вертикальная красная метка по-прежнему находится в середине стековой панели:
Комментарии:
1. по сути, вы боретесь с макетом (и заставляете его делать то, что вы хотите, неправильно используя margin is .. evil 😉 — поиск управляемого дочернего элемента с помощью некоторого внешнего кода будет отменен при каждом проходе макета.
2. Похоже, у вас есть
Controller
код в классе, который расширяетсяApplication
.3. @kleopatra: какой макет лучше использовать?
Ответ №1:
Установите поля программно и используйте вставки (двойной верх, двойной правый, двойной нижний, двойной левый)
@FXML
private void moveTimeMark( MouseEvent e ) {
final double x = e.getX();
System.err.printf( "%7.2fn", x );
StackPane.setMargin(timeMark, new Insets(0,x,0,0));
}
Комментарии:
1. Нет, это не решает проблему. Запустите его.
Ответ №2:
setMargin решает проблему с помощью небольшого исчисления:
@FXML
private void moveTimeMark( MouseEvent e ) {
StackPane.setMargin( timeMark,
new Insets( 0.0, 0.0, 0.0, -timeMarkContainer.getWidth() 2.0*e.getX()));
}
Зачем нужно это исчисление?