Статьи

От вкладок до TabuLESS для платформы NetBeans с использованием JavaFX и CSS!

В этой статье будут продемонстрированы несколько приемов визуального улучшения приложения на платформе NetBeans со встроенными элементами управления JavaFX. Он будет основан на предыдущих руководствах, демонстрирующих полную замену компонентов Swing NetBeans по умолчанию с использованием JavaFX. Примеры кода будут включать платформу NetBeans, JavaFX и CSS.

В предыдущих руководствах по интеграции JavaFX с платформой NetBeans мы показали, как заменить панель меню и панель инструментов NetBeans Swing элементами управления типа аккордеон на основе JavaFX, которые выдвигаются с боковой стороны экрана. Мы назвали их AccordionMenu и Accordion Toolbar, и они не только высвободили ценное вертикальное пространство, но и стали более удобными для сенсорных дисплеев. Когда эти элементы управления не используются, они вставляются и автоматически минимизируются. 

Вы можете найти эти уроки здесь: 

И они сами являются продолжением этих замечательных статей, написанных Гертжаном Виленгой :

Чтобы полностью понять и следовать этому руководству, вам нужно начать с предыдущих руководств, упомянутых выше. 

Скрыть вкладку и границу SlideIn 

Как бы ни выгляделы компоненты Accordion при встраивании в слайд платформы NetBeans В TopComponent были небольшие визуальные проблемы. Например, слайд TopComponent отображается в компоненте контейнера TabDisplayer, который отображает свою собственную границу. Таким образом, каждый раз, когда ваш компонент Slide In изменяется, вы, вероятно, увидите эту границу:

эта граница раздражает, как и вкладка TitleBar. Я хочу видеть,
что Блог Geertjan’s   не компонентные артефакты. После многих раздражающих поисков я обнаружил, что Платформа поддерживает скрытие этих вещей с помощью какого-либо опубликованного интерфейса. Однако немного взлома и мы можем это сделать.

Сначала сделайте все непрозрачным и прозрачным. Ниже мой конструктор TopComponent, модифицированный для поддержки прозрачности:

public final class SlidingAccordionTopComponent extends TopComponent {
    public AccordionMenu accordionMenu = new AccordionMenu();
    private TopComponent me;
    
    public SlidingAccordionTopComponent() {
        initComponents();
        setName(Bundle.CTL_SlidingAccordionTopComponent());
        setToolTipText(Bundle.HINT_SlidingAccordionTopComponent());
        putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
        putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, Boolean.TRUE);
        putClientProperty(TopComponent.PROP_MAXIMIZATION_DISABLED, Boolean.TRUE);
        putClientProperty(TopComponent.PROP_UNDOCKING_DISABLED, Boolean.TRUE);
        putClientProperty(TopComponent.PROP_KEEP_PREFERRED_SIZE_WHEN_SLIDED_IN, Boolean.TRUE);

        me = this;
        setLayout(new BorderLayout());
        add(accordionMenu,BorderLayout.CENTER);
        Color transparent = new Color(0.0f, 0.0f, 0.0f, 0.0f);
        setOpaque(true);
        setBackground(transparent);
        accordionMenu.setOpaque(true);
        accordionMenu.setBackground(transparent);
        validate();
    }

Затем добавьте зависимость библиотеки «Tab Control» в ваш модуль. 
Наконец, мы @Override для компонента TopComponentShowing (), чтобы найти TabDisplayer и скрыть его и его уродливую границу:

    @Override
    protected void componentShowing() {
        super.componentShowing(); 
        Container parent = me.getParent();
        Container parent2 = parent.getParent();

        Component [] comps = parent2.getComponents();
        for(int i=0;i<comps.length;i++) {
            if(comps[i].getClass().getName().equals(TabDisplayer.class.getName())) {
                TabDisplayer td = (TabDisplayer)comps[i];
                td.setVisible(false);
            }
            else {
                JPanel theJPanel = (JPanel) comps[i];
                theJPanel.setBorder(BorderFactory.createEmptyBorder());
            }
        }        
        this.validate();
    }

I suppose the way I searched for the TabDisplayer through the ancestor tree is a little hackish but it is quite effective.  Below is the same component with the above fix, rendered in Fullscreen mode:

Style the JavaFX components with CSS

Now that we have visually isolated our JavaFX component from the underlying Swing platform, we can make it look a bit more striking.  Using CSS with JavaFX is nothing new.  Below I merely want to demonstrate the points to add the CSS and what is possible when CSS and JavaFX are combined with the NetBeans Platform. Its tremendously easy to do which of course is the obvious benefit of embedding JavaFX components within the NetBeans Platform in the first place.  Below is the update to my createScene() method where the JavaFX scene is constructed.

        Group g = new Group();        
        Scene scene = new Scene(g, 400, 500,new Color(0.0,0.0,0.0,0.0));
        //PlatformImpl.setDefaultPlatformUserAgentStylesheet();
        //Application.setUserAgentStylesheet(null);
        scene.getStylesheets().add(metroDarkCSS);
        scene.getStylesheets().add(control2CSS);
 
        accordionPane = new Accordion();
        accordionPane.getPanes().addAll(titledPaneList); 
        g.getChildren().add(accordionPane);
        setScene(scene);
        validate();
        setOpaque(true);
        setBackground(new java.awt.Color(0.0f, 0.0f, 0.0f, 0.0f));

Some key points… I’ve left commented out two lines of code that you may need if you are using an early developers release of JDK 8.  With JDK 7u21 I did not need them. 

I’ve added two different CSS and they’ll mix with each other for some Frankenstienish results but its all fun.  I got the metroDarkCSS sheet from Pedro Duque Vieira.  Amazing job Pedro, honestly way more work then this tutorial really.  Below is just the control2css style sheet:

.root{
    -fx-font-size: 16pt;
    -fx-font-family: "Courier New";
    -fx-base: rgb(132, 145, 47);
    -fx-background: rgb(225, 228, 203);
}

.button{
    -fx-text-fill: rgb(49, 89, 23);
    -fx-border-color: rgb(49, 89, 23);
    -fx-border-radius: 5;
    -fx-padding: 3 6 6 6;
}

.borders{
    -fx-border-color: rgb(103, 100, 78);
    -fx-border-style: dotted;
    -fx-border-width: 1.5;
    -fx-border-insets: -5;
}

And here is what our AccordionMenu component looks like skinned with the control2css style sheet:

Which really looks nice overlayed on a WorldWind tool because it has a cool Earthy look and feel.

Now lets switch to the Dark Metro look:

Not bad… I like the blocky look but not the grey… lets gob them together:

Hey pretty neat.  One thing… notice in the above screenshot the grey bar at the bottom of the menu?  That is where the JavaFX scene extends past the menu components.  But didn’t we implement transparency all over the place?  Sure but as of right now JavaFX scenes don’t play nice with Z-ordering with Native heavyweight components, which WorldWind is one.  You won’t have that problem with any other Swing or JavaFX components of course.

For example lets apply all these types of changes to our similar Toolbar component.  Below is the CSS that I’m inlining to the AccordionToolbar:

newToolbarFromFileObject.setStyle("    -fx-text-fill: rgb(49, 89, 23);\n" +
"    -fx-border-color: rgb(49, 89, 23);\n" +
"    -fx-border-radius: 5;\n" +     
"    -fx-border-style: dotted;" +
"    -fx-border-width: 1.5;"  +
"    -fx-padding: 3 6 6 6;");

and I even mix it with an existing CSS like in the AccordionMenu example above using the scene.getStylesheets().add() pattern.  Below is that CSS:

.root{
    -fx-font-size: 14pt;
    -fx-font-family: "Tahoma";
    -fx-base: #DFB951;
    -fx-background: #A78732;
    -fx-focus-color: #B6A678;
}

.button1{
    -fx-text-fill: #006464;
    -fx-background-color: #DFB951;
    -fx-border-radius: 20;
    -fx-background-radius: 20;
    -fx-padding: 5;
}

.button2{
    -fx-text-fill: #c10000;
    -fx-background-color: #DFB951;
    -fx-border-radius: 20;
    -fx-background-radius: 20;
    -fx-padding: 5;
}

.slider{
    -fx-border-color: white;
    -fx-border-style: dashed;
    -fx-border-width: 2;
}

And we get something like this:

Oh but UGH that TabDisplayer is biting us!!!  Let’s apply the tab hack:

Hey that’s nice!  We got rid of all the remnants of borders and tabs yet completely retained our access to the Menu and Toolbar.  

Congratulations!  You’ve gone from tabs… to ** TABULESS **!!