简体   繁体   English

是否可以以某种方式拥有两个主视图和一个局部视图?

[英]Is it somehow possible to have two master views and one detail view?

If I have for example one master view on the left and one in the middle, each showing oder Java Beans/POJOs, can I use a shared detail view that somehow listens to the active beans of each view and then displays the currently selected one in more detail? 例如,如果我在左侧有一个主视图,在中间有一个主视图,每个主视图都显示了Java Beans / POJO,我可以使用共享的详细视图,以某种方式侦听每个视图的活动bean,然后在其中显示当前选择的一个视图。更多详情? A one to one relation is quite easy to manage by using your Context library. 通过使用上下文库,一对一关系非常容易管理。

@ViewDocking(areaId ="left", position=1, displayName="Profiles", menuEntry = @WindowMenuEntry(path = "", position=0), accelerator="Shortcut+1")
public class ProfileListView extends BorderPane implements LocalContextProvider {

private final SimpleContextContent content = new SimpleContextContent();

private final SimpleContext context = new SimpleContext(content);

@FXML
private ListView<Profile> listview;

public ProfileListView() {
    load();
    // add some profiles
    listview.getItems().add(new Profile("Profile1"));
    listview.getItems().add(new Profile("Profile2"));
    listview.getItems().add(new Profile("Profile3"));

    // setup selection listener
    listview.getSelectionModel().selectedItemProperty().addListener((value, oldProfile, newProfile) -> {
        // set active profile and remove old one
        content.remove(oldProfile);
        content.add(newProfile);
    });

    // setup double click listener
    configureClickListener();
}

private Profile getSelectedProfile() {
    return listview.getSelectionModel().getSelectedItem();
}

private void configureClickListener() {
    listview.setOnMouseClicked(event -> {
        // check if it was a double click
        if(event.getClickCount() == 2) {
            System.out.println(getSelectedProfile());
            // inject into editor pane
            // calls the procedure to create a tab in the center area...
        }
    });
}

private void load() {
    FXMLLoaders.loadRoot(this);
}

@Override
public Context getLocalContext() {
    return context;
}
}

This is one master view holding a list view of items. 这是一个主视图,其中包含项的列表视图。 The other one would be the same, docking to the right as another tab and holding POJOs of type 'Action'. 另一个将是相同的,与另一个选项卡停靠在右侧,并持有“ Action”类型的POJO。

The detail view is here: 详细视图在这里:

@ViewDocking(areaId = "right", displayName = "Properties", accelerator = "Shortcut+2", menuEntry = @WindowMenuEntry(path = "", position = 0), position = 1)
public class ProfilePropertiesView extends BorderPane implements LocalContextProvider, ActiveContextSensitive {

private Context activeContext;

private SimpleContextContent content = new SimpleContextContent();

private SimpleContext context = new SimpleContext(content);

private Profile profile;

private IWindowService service = new NullWindowService();

@FXML
private PropertySheet propertysheet;

public ProfilePropertiesView() {
    load();
    // retrieve framework service, TODO: use tracker
    BundleContext ctx = FrameworkUtil.getBundle(getClass()).getBundleContext();
    service = ctx.getService(ctx.getServiceReference(IWindowService.class));
    // initialize callback
    service.addCallback(title -> {
        System.out.println("callback called " + title);
        // update the property sheet ui by re-creating the items list
       // updateUI();
        // we can safely return null
        return null;
    });

    // configure editor factory so the user is able to use a combobox
    propertysheet.setPropertyEditorFactory(new CustomPropertyEditorFactory(service));
}

private void load() {
    FXMLLoaders.loadRoot(this);
}

@Override
public Context getLocalContext() {
    return context;
}

private void contextChanged() {
    // find profile information
    Profile found = activeContext.find(Profile.class);
    // if the found profile is null, ignore it
    if (found != null) {
        // reset if profile is valid
        if (profile != null) {
            reset();
        }
        // create reference and register
        profile = found;
        register();
    }
}

private void register() {
    // retrieve observablelist of bean properties if some profile is selected
    if(profile != null) {
        ObservableList<Item> items = createDetailedList(profile);
        propertysheet.getItems().setAll(items);
    }
}

private void updateUI() {
    // clear property elements and re-create them
    reset();
    // re-create items
    ObservableList<Item> items = createDetailedList(profile);
    propertysheet.getItems().addAll(items);
}

private ObservableList<Item> createDetailedList(Object bean) {
    ObservableList<Item> list = FXCollections.observableArrayList();
    try {
        BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass(), Object.class);
        Arrays.stream(beanInfo.getPropertyDescriptors()).map(pd -> new DetailedBeanProperty(bean, pd)).forEach(list::add);
    } catch (IntrospectionException e) {
        e.printStackTrace();
    }

    return list;
}

private void reset() {
    propertysheet.getItems().clear();
}

@Override
public void setActiveContext(Context activeContext) {
    this.activeContext = activeContext;
    this.activeContext.addContextListener(Profile.class, event -> contextChanged());
    // trigger change
    contextChanged();
}
}

The current ProfilePropertiesView is just configured to display the properties of the selected profile. 当前的ProfilePropertiesView只是配置为显示所选配置文件的属性。 I want it to be able to display the current information of the last selected POJO in the UI. 我希望它能够在UI中显示最后选择的POJO的当前信息。 That means that if the user selected a Profile from the ListView, that profile should be displayed in the properties view. 这意味着,如果用户从ListView中选择了一个配置文件,则该配置文件应显示在属性视图中。 If he selected an Action from the Table (which is displayed in the center), the properties of the Action should be displayed. 如果他从表格(显示在中间)中选择了一个动作,则应该显示该动作的属性。

Do I just need to register a new ContextListener for the Action.class POJO and then call a method to populate the PropertiesView? 我是否只需要为Action.class POJO注册一个新的ContextListener,然后调用一个方法来填充PropertiesView? I was unsure if this is the right solution... 我不确定这是否是正确的解决方案...

Yes, just add another ContextListener to the activeContext for every POJO type you want to observe. 是的,只需为您要观察的每种POJO类型向activeContext添加另一个ContextListener

Also note that in the constructor of views it's better to use a ServiceTracker instead of looking for the service via BundleContext as the service might not be available yet, depending on the order the bundles are loaded. 还要注意,在视图的构造函数中,最好使用ServiceTracker而不是通过BundleContext查找服务,因为该服务可能尚不可用,具体取决于捆绑包的加载顺序。

You can find a sample which uses a ServiceTracker here: https://stackoverflow.com/a/35974498/506855 您可以在此处找到使用ServiceTracker的示例: https : //stackoverflow.com/a/35974498/506855

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM