Make a slideshow tool with JavaFX

Overview

In November 2016, I thought, "If you want to have a JavaFX session, let's make a slideshow tool with JavaFX", so I just did it, so I decided to leave it in the article.

A slide show is a coined word that combines slide and show, and seems to be one word. [Wikipedia Japanese version of the article](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%A9%E3%82%A4%E3%83%89%E3%82% It was written in B7% E3% 83% A7% E3% 83% BC).

Achievements of ancestors

There are many implementation examples of slide show (presentation) tools using JavaFX, including Mr. Sakuraba of Java Champion.

-Presentation tool with JavaFX -Tools for making slides in Markdown with JavaFX

Why did you make it yourself without using the existing ones?

I just wanted to implement it in a way that was easy for me to use.


Functions required for slide show tools

――Characters and images can be displayed in full screen …… Put Pane with Label in Scene and display in full screen? --Multiple slides can be switched and displayed --You can describe the contents of the slide with some kind of markup ... Markdown? --You can convert slides to PDF ... Make screenshots into one file?

How to implement?

I think there are several ways to do it.

-Create content with reveal.js or Remark.js and display it in WebView …… It looks good when made with this, and it is easy to arrange and convert to PDF. --Display PDF content --Convert content to JavaFX Pane for display

I've already done 1 so I decided to make it all in JavaFX this time.


Execution environment

Name version
Java SE 1.8.0_121
OS Windows 10
Eclipse 4.5
Gradle 3.0

Implementation

I put the whole source code in the GitHub repository below.

The points are introduced below.

Content description

Allowed developers to write content in Markdown, which they are familiar with on Qiita and GitHub. The degree of freedom is low, but you can easily prepare the content as shown below.

# Title
toastkidjp

##About this slide 1234567890123456789012345678901234567890
The other day, java with momentum.io.I've replaced the code that used File with Path and Files, so I'll introduce it from the perspective of rewriting the existing code. If you're already familiar with NIO2, you probably won't notice anything after reading this article.

By the way, the new file-related API from JDK7 is NIO2(New I/O 2)It seems that it is called, MUJI is 1.It seems to refer to Channels and Charsets added in the 4th era.

##Code can also be placed

` ``java
(1..100)
  .collect{it % 15 == 0 
           ? "FizzBuzz" 
           :  it % 3 ==0 
               ? "Fizz" 
               : it % 5 == 0
                   ? "Buzz" 
                   : it
                   }
  .forEach{print it + ", "}
` ``

#that's all
Thank you very much.

Note that I can't use JavaCC, so Parser is a childish implementation that reads the text of the Markdown file line by line ...

Implementation of slides

In order to display the scroll bar when the height of the content exceeds the height of the display, we have implemented an implementation that inherits ScrollPane and puts a Pane that collects Nodes that display strings and images in the Content.

Put all slides in List, 1 Draw on StackPane and only current ones Is displayed, and everything else is hidden.

Label characters are truncated

If you use the default Label object, strings that exceed the display area will not be displayed and will be truncated.

ss6.png

The following settings have been made to the Label object.

Settings to prevent strings from being truncated


label.setWrapText(true);
label.setMinHeight(Region.USE_PREF_SIZE);

ss6_.png

Content height exceeds display height

With reference to the Qiita slide method, vertical scrolling is possible when the slide exceeds the display height. Specifically, the Slide class inherits ScrollPane and makes the following settings in the constructor. This allows you to disable side-scrolling and bring up the vertical scroll bar only when you need it.

Disable side-scrolling and bring up a vertical scroll bar only when needed


this.setHbarPolicy(ScrollBarPolicy.NEVER);
this.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);

ss1.png ss3.png

In addition, I think that it is because many Slide objects are overlapped, but since I could not move the scroll bar with the mouse, I am trying to move it by calling the following method with a keyboard shortcut.

Scroll up


setVvalue(getVvalue() - 0.20d);

Scroll down


setVvalue(getVvalue() + 0.20d);

Connecting submenu and Main class

Considering the ease of operation, we have prepared the following submenus.

ss5.png

The submenu Controller and the Main class, which implements specific functions, are separate classes. It is necessary to pass the event received in the submenu to the Main class for processing. There are several ways to do this, this time using a library called Reactor.

Preparation of message class

Prepare various message classes to convey what you want the Main class to process. Create each class as an implementation of the Message interface.

Accept UI events from users and send a message to Main

Create an event object with the @FXML annotated method and pass it to the Main class using TopicProcessor. TopicProcessor creates an instance when the submenu class is initialized, passes the object to the Main class via getter, subscribes in the Main class, and branches to the processing according to the implementation type of the event in subscribe.

This implementation is based on the mechanism called EventBus used in Android application development.

important point

Since the execution thread of the method called from TopicProcessor is not the JavaFX application thread, you need to use Platform.runLater to execute the drawing related processing.

The drawback of adopting this mechanism is that the Main class is simply bloated. This time I'm compromising on this.

PDF file of slide show

In most cases, you may need to distribute a PDF of the slideshow as a resource. In preparation for such a case, we are also creating a PDF conversion function.

Convert all slides to PDF using PDFBox


try (final PDDocument doc = new PDDocument()) {
    final int width  = (int) stage.getWidth();
    final int height = (int) stage.getHeight();
    Interval.oneTo(slides.size()).each(i ->{
        moveTo(i);
        final long istart = System.currentTimeMillis();
        final PDPage page = new PDPage(new PDRectangle(width, height));
        try (final PDPageContentStream content = new PDPageContentStream(doc, page)) {
            content.drawImage(LosslessFactory.createFromImage(
                    doc, slides.get(current.get() - 1).generateImage(width, height)), 0, 0);
        } catch(final IOException ie) {
            LOGGER.error("Occurred Error!", ie);
        }
        doc.addPage(page);
        LOGGER.info("Ended page {}. {}[ms]", i, System.currentTimeMillis() - istart);
    });
    doc.save(new File(DEFAULT_PDF_FILE_NAME));
} catch(final IOException ie) {
    LOGGER.error("Occurred Error!", ie);
}

I flip through the slides one by one, take captured images of each slide, and combine those images into a single PDF file using a library called PDFBox.

When I tried it, it took 1 second to convert 4 slides to PDF.

2017-02-16 23:32:30  INFO Main Ended page 1. 334[ms]
2017-02-16 23:32:31  INFO Main Ended page 2. 269[ms]
2017-02-16 23:32:31  INFO Main Ended page 3. 181[ms]
2017-02-16 23:32:31  INFO Main Ended page 4. 169[ms]
2017-02-16 23:32:31  INFO Main Ended generating PDF. 1032[ms]

By the way, Interval is Eclipse Collections A class in .eclipse.org/collections/ja/).

The PDF file prepared for the actual presentation has been uploaded to Speaker Deck. https://speakerdeck.com/toastkidjp/jjug-ccc-2016-fall-number-ccc-l5

Sample code display

It seems that the source code is often shown in the developer's presentation. It's hard to see the code as it is in Label, so I used a library (CodeArea) called RichTextFX which is an implementation of TextArea that can be highlighted.

As an example, Groovy's FizzBuzz can be displayed with syntax highlighting as shown below.

ss4.png

Task

JVM crashes when exiting application directly from full screen

I don't know the cause well ... By the way, in the case of gradle run, a similar error message is displayed, but it ends normally.

Console message


#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00000000737b584a, pid=15116, tid=0x000000000000246c
#
# JRE version: Java(TM) SE Runtime Environment (8.0_102-b14) (build 1.8.0_102-b14)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.102-b14 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C  [glass.dll+0x2584a]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# /path/to/slide_show/hs_err_pid15116.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#

Full text

https://gist.github.com/toastkidjp/1d216a9ad98a65dd0bc42552dfe99791

Display collapse when the display size changes

I think it's because the display area is variable, but ... The existing tools that do well in this area are wonderful. I'm wondering if I can apply the method of acquiring the display size used by Mr. Takahashi and dynamically changing the font size in JJUG CCC 2016 Fall, but I haven't tried it yet.

When I used this tool before, I had a break of 30 minutes, so I carefully checked for display corruption there.


Summary

So far, I have introduced one of the ways to create a slideshow using JavaFX. Well, it's easier, safer and more powerful to use PowerPoint or LibreOffice normally. If it is a Qiita slide, you can publish it as an article as it is and it is easy to share. At this point, it's too lacking in functionality, and complacency accounts for a significant part of the reason for using it.

However, it seems that JavaFX can be used not only in Java but also in languages that run on the JVM, so I hope this article will be useful for those who want to give a slightly different presentation.

Link

Library used

Referenced library

Repository

Recommended Posts

Make a slideshow tool with JavaFX
Make a digging maze with Ruby2D
Make a Christmas tree with swift
Make a garbage reminder with line-bot-sdk-java
Make a list map with LazyMap
Make a typing game with ruby
Let's make a Christmas card with Processing!
Make a family todo list with Sinatra
Let's make a smart home with Ruby!
Make a login function with Rails anyway
[docker] [nginx] Make a simple ALB with nginx
Tool creation with JavaFX & self-contained package (distribution)
Make a site template easily with Rails
Tool creation with JavaFX & self-contained package (JavaFX edition)
HelloFX with JavaFX
Creating a browser automation tool with Ruby + Selenium
Let's make a search function with Rails (ransack)
Make System.out a Mock with Spock Test Framework
A simple rock-paper-scissors game with JavaFX and SceneBuilder
I tried to make a simple game with Javafx ① "Let's find happiness game" (unfinished)
Run Scala with GraalVM & make it a native image
Merry Christmas with JavaFX !!
How to make a factory with a model with polymorphic association
I tried to make a simple game with Javafx ① "Let's find happiness game" (unfinished version ②)
Make Calendar gadgets made with JavaFX compatible with Java SE 9
Let's make a LINE Bot with Ruby + Sinatra --Part 2
[Java basics] Let's make a triangle with a for statement
[Personal application work memo] Make a calendar with simple_calendar
Make JavaFX / TableView editable
Make a reflection utility ②
Make a reflection utility ③
Let's make a LINE Bot with Ruby + Sinatra --Part 1
Make a reflection utility ①
Make an Ev3 radio control with JavaFx and leJOS [Part 2]
[Beginner] Try to make a simple RPG game with Java ①
I want to make a list with kotlin and java!
I want to make a function with kotlin and java!
Make a simple CRUD with SpringBoot + JPA + Thymeleaf ① ~ Hello World ~
Learning Ruby with AtCoder 13 How to make a two-dimensional array
Let's make a simple API with EC2 + RDS + Spring boot ①
Make an Ev3 radio control with JavaFx and leJOS [Part 1]
Make a simple CRUD with SpringBoot + JPA + Thymeleaf ⑤ ~ Template standardization ~
Microservices with DevOps Make Changes
Create a playground with Xcode 12
[Note] Scene transition with JavaFX
Draw a gradient with CAGradientLayer
[Java] Make it a constant
[Rails] Make a breadcrumb trail
Make a rhombus using Java
A story stuck with NotSerializableException
Let's make a book management web application with Spring Boot part1
I want to make a button with a line break with link_to [Note]
A tool to generate Retina images for iOS for use with Xcode
How to make a jar file with no dependencies in Maven
Let's make a book management web application with Spring Boot part3
Try to make a cross-platform application with JRuby (jar file generation)
Let's make a book management web application with Spring Boot part2
Make a C compiler to use with Rust x CLion with Docker
I wanted to make JavaFX programming easier with the Spring Framework
I tried to make a group function (bulletin board) with Rails