반응형

 

linux를 처음 알고 시작했을 당시만해도 xmms라는 콘솔에서 실행하는 프로그램을 설치하고 음악을 듣곤 했었는데, 거기서부터 파생된 gui형태의 프로그램들이 많이 나온것 같습니다. xmms2도 있었고, audacious라는 프로그램을 최근까지도 메인으로 사용하고 있었는데, 얼마전 qmmp라는 또다른 프로그램을 알게 되었습니다. 이름에서 알 수 있듯이 QT기반의 프로그램 이라고 합니다. 어떤 녀석인지 한 번 설치해 보도록 하겠습니다.

현재 제 데스크탑에는 ubuntu 20.04 lts가 설치되어 있습니다. 그래서 ubuntu package manager로 가서 qmmp를 찾아봅니다. 2개가 나오는데 어떤걸까요? 아래쪽이 1.5 버전이라고 되어있어서 아래쪽 프로그램을 설치하겠습니다.

설치하고 나니 보이긴 하는데, 아이콘이 안나오네요...ㅠㅠ

 

프로그램 실행은 문제가 없어 보입니다.

아이콘이 안나오는게 찜찜하네요. 아까 설치하지 않은 1.3버전을 설치해보도록 하겠습니다. 혹시 모르니 qmmp 사이트에서 repository를 추가한 후 업데이트를 합니다.

sudo add-apt-repository ppa:forkotov02/ppa
sudo apt update

 

나비모양의 아이콘이 있는 Qmmp가 하나 더 설치되었습니다.

실행해보니 버전이 1.6.1??

저장소 업데이트가 효과가 있었나봅니다. 먼저 설치했던(아이콘 안나오는..) 1.5버전을 삭제했습니다. 그래도 실행이 잘 되네요..^^;;

 

스킨을 한번 변경해보겠습니다. 구글에서 qmmp skin 이라고 검색하고 확장자가 .wsz인 파일 몇개를 다운받아 놓습니다. 어떤 분이 몇가지 스킨을 모아놓으셔서 링크를 공유해드립니다. 다운받은 뒤 Qmms 우클릭 > 설정 > 모양새 > 스킨 > 추가...로 받아놓은 스킨 파일들을 추가해줍니다.

적당한 스킨을 하나 클릭하여 "닫기" 버튼을 클릭하면..

잘 적용이 되네요~

반응형
반응형

JavaFX에서 css파일을 적용하는 방법에 대해 알아보겠습니다.

 

1. CSS 파일 추가

"resources - 프로젝트이름폴더" 하위에 css파일을 추가합니다. 샘플로 darktheme.css라고 이름지었습니다.

2. CSS파일 적용

HelloApplication클래스의 Scene 선언부 바로 뒤에 darktheme을 불러오는 코드를 추가합니다.

package com.example.test07;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;


public class HelloApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
        Scene scene = new Scene(fxmlLoader.load(), 1024, 760);
        scene.getStylesheets().add(getClass().getResource("darktheme.css").toString()); //코드 추가

        stage.setTitle("Hello!");
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

 

3. CSS샘플 코드(darktheme.css)

웹에서 사용하는 CSS문법과 거의 비슷한데, 속성 앞에 "-fx-"가 들어갑니다. WPF보다 너무 편한것 같네요.

.root {
    -fx-background-color: #f3f3f3;
}
.button {
    -fx-background-radius: 15px;
    -fx-background-color:
        rgba(0,0,0,0.08),
        linear-gradient(#9a9a9a, #909090),
        linear-gradient(white 0%, #f3f3f3 50%, #ececec 51%, #f2f2f2 100%);
    -fx-background-insets: 0 0 -1 0,0,1;
    -fx-padding: 3 30 3 30;
    -fx-text-fill: #242d35;
    -fx-font-size: 14px;
}
.button:hover{
    -fx-background-radius: 15px;
    -fx-background-color:
            rgba(0,0,0,0.08),
            linear-gradient(#5a61af, #51536d),
            linear-gradient(#e4fbff 0%,#cee6fb 10%, #a5d3fb 50%, #88c6fb 51%, #d5faff 100%);
    -fx-background-insets: 0 0 -1 0,0,1;

    -fx-padding: 3 30 3 30;
    -fx-text-fill: #242d35;
    -fx-font-size: 14px;
}

 

4. 결과

 

5. 기타 다른 스타일의 샘플 

Mac의 OSX 스타일 찾다보니 여기까지 오게 되었습니다. 버튼은 아래의 여러가지 스타일을 참고해서 만들면 좋을 것 같습니다.

#green {
    -fx-background-color:
        linear-gradient(#f0ff35, #a9ff00),
        radial-gradient(center 50% -40%, radius 200%, #b8ee36 45%, #80c800 50%);
    -fx-background-radius: 6, 5;
    -fx-background-insets: 0, 1;
    -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.4) , 5, 0.0 , 0 , 1 );
    -fx-text-fill: #395306;
}
#round-red {
    -fx-background-color: linear-gradient(#ff5400, #be1d00);
    -fx-background-radius: 30;
    -fx-background-insets: 0;
    -fx-text-fill: white;
}
#bevel-grey {
    -fx-background-color: 
        linear-gradient(#f2f2f2, #d6d6d6),
        linear-gradient(#fcfcfc 0%, #d9d9d9 20%, #d6d6d6 100%),
        linear-gradient(#dddddd 0%, #f6f6f6 50%);
    -fx-background-radius: 8,7,6;
    -fx-background-insets: 0,1,2;
    -fx-text-fill: black;
    -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 5, 0.0 , 0 , 1 );
}
#glass-grey {
    -fx-background-color: 
        #c3c4c4,
        linear-gradient(#d6d6d6 50%, white 100%),
        radial-gradient(center 50% -40%, radius 200%, #e6e6e6 45%, rgba(230,230,230,0) 50%);
    -fx-background-radius: 30;
    -fx-background-insets: 0,1,1;
    -fx-text-fill: black;
    -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 3, 0.0 , 0 , 1 );
}
#shiny-orange {
    -fx-background-color: 
        linear-gradient(#ffd65b, #e68400),
        linear-gradient(#ffef84, #f2ba44),
        linear-gradient(#ffea6a, #efaa22),
        linear-gradient(#ffe657 0%, #f8c202 50%, #eea10b 100%),
        linear-gradient(from 0% 0% to 15% 50%, rgba(255,255,255,0.9), rgba(255,255,255,0));
    -fx-background-radius: 30;
    -fx-background-insets: 0,1,2,3,0;
    -fx-text-fill: #654b00;
    -fx-font-weight: bold;
    -fx-font-size: 14px;
    -fx-padding: 10 20 10 20;
}
#dark-blue {
    -fx-background-color: 
        #090a0c,
        linear-gradient(#38424b 0%, #1f2429 20%, #191d22 100%),
        linear-gradient(#20262b, #191d22),
        radial-gradient(center 50% 0%, radius 100%, rgba(114,131,148,0.9), rgba(255,255,255,0));
    -fx-background-radius: 5,4,3,5;
    -fx-background-insets: 0,1,2,0;
    -fx-text-fill: white;
    -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 5, 0.0 , 0 , 1 );
    -fx-font-family: "Arial";
    -fx-text-fill: linear-gradient(white, #d0d0d0);
    -fx-font-size: 12px;
    -fx-padding: 10 20 10 20;
}
#dark-blue Text {
    -fx-effect: dropshadow( one-pass-box , rgba(0,0,0,0.9) , 1, 0.0 , 0 , 1 );
}
#record-sales {
    -fx-padding: 8 15 15 15;
    -fx-background-insets: 0,0 0 5 0, 0 0 6 0, 0 0 7 0;
    -fx-background-radius: 8;
    -fx-background-color: 
        linear-gradient(from 0% 93% to 0% 100%, #a34313 0%, #903b12 100%),
        #9d4024,
        #d86e3a,
        radial-gradient(center 50% 50%, radius 100%, #d86e3a, #c54e2c);
    -fx-effect: dropshadow( gaussian , rgba(0,0,0,0.75) , 4,0,0,1 );
    -fx-font-weight: bold;
    -fx-font-size: 1.1em;
}
#record-sales:hover {
    -fx-background-color: 
        linear-gradient(from 0% 93% to 0% 100%, #a34313 0%, #903b12 100%),
        #9d4024,
        #d86e3a,
        radial-gradient(center 50% 50%, radius 100%, #ea7f4b, #c54e2c);
}
#record-sales:pressed {
    -fx-padding: 10 15 13 15;
    -fx-background-insets: 2 0 0 0,2 0 3 0, 2 0 4 0, 2 0 5 0;
}
#record-sales Text {
    -fx-fill: white;
    -fx-effect: dropshadow( gaussian , #a30000 , 0,0,0,2 );
}
#rich-blue {
    -fx-background-color: 
        #000000,
        linear-gradient(#7ebcea, #2f4b8f),
        linear-gradient(#426ab7, #263e75),
        linear-gradient(#395cab, #223768);
    -fx-background-insets: 0,1,2,3;
    -fx-background-radius: 3,2,2,2;
    -fx-padding: 12 30 12 30;
    -fx-text-fill: white;
    -fx-font-size: 12px;
}
#rich-blue Text {
    -fx-effect: dropshadow( one-pass-box , rgba(0,0,0,0.8) , 0, 0.0 , 0 , 1);
}
#big-yellow {
    -fx-background-color: 
        #ecebe9,
        rgba(0,0,0,0.05),
        linear-gradient(#dcca8a, #c7a740),
        linear-gradient(#f9f2d6 0%, #f4e5bc 20%, #e6c75d 80%, #e2c045 100%),
        linear-gradient(#f6ebbe, #e6c34d);
    -fx-background-insets: 0,9 9 8 9,9,10,11;
    -fx-background-radius: 50;
    -fx-padding: 15 30 15 30;
    -fx-font-family: "Helvetica";
    -fx-font-size: 18px;
    -fx-text-fill: #311c09;
    -fx-effect: innershadow( three-pass-box , rgba(0,0,0,0.1) , 2, 0.0 , 0 , 1);
}
#big-yellow Text {
    -fx-effect: dropshadow( one-pass-box , rgba(255,255,255,0.5) , 0, 0.0 , 0 , 1);
}
#iphone-toolbar {
    -fx-background-color: linear-gradient(#98a8bd 0%, #8195af 25%, #6d86a4 100%);
}
#iphone {
    -fx-background-color: 
        #a6b5c9,
        linear-gradient(#303842 0%, #3e5577 20%, #375074 100%),
        linear-gradient(#768aa5 0%, #849cbb 5%, #5877a2 50%, #486a9a 51%, #4a6c9b 100%);
    -fx-background-insets: 0 0 -1 0,0,1;
    -fx-background-radius: 5,5,4;
    -fx-padding: 7 30 7 30;
    -fx-text-fill: #242d35;
    -fx-font-family: "Helvetica";
    -fx-font-size: 12px;
    -fx-text-fill: white;
}
#iphone Text {
    -fx-effect: dropshadow( one-pass-box , rgba(0,0,0,0.8) , 0, 0.0 , 0 , -1 );
}
#ipad-dark-grey {
    -fx-background-color: 
        linear-gradient(#686868 0%, #232723 25%, #373837 75%, #757575 100%),
        linear-gradient(#020b02, #3a3a3a),
        linear-gradient(#9d9e9d 0%, #6b6a6b 20%, #343534 80%, #242424 100%),
        linear-gradient(#8a8a8a 0%, #6b6a6b 20%, #343534 80%, #262626 100%),
        linear-gradient(#777777 0%, #606060 50%, #505250 51%, #2a2b2a 100%);
    -fx-background-insets: 0,1,4,5,6;
    -fx-background-radius: 9,8,5,4,3;
    -fx-padding: 15 30 15 30;
    -fx-font-family: "Helvetica";
    -fx-font-size: 18px;
    -fx-font-weight: bold;
    -fx-text-fill: white;
    -fx-effect: dropshadow( three-pass-box , rgba(255,255,255,0.2) , 1, 0.0 , 0 , 1);
}
#ipad-dark-grey Text {
    -fx-effect: dropshadow( one-pass-box , black , 0, 0.0 , 0 , -1 );
}
#ipad-grey {
    -fx-background-color: 
        linear-gradient(#686868 0%, #232723 25%, #373837 75%, #757575 100%),
        linear-gradient(#020b02, #3a3a3a),
        linear-gradient(#b9b9b9 0%, #c2c2c2 20%, #afafaf 80%, #c8c8c8 100%),
        linear-gradient(#f5f5f5 0%, #dbdbdb 50%, #cacaca 51%, #d7d7d7 100%);
    -fx-background-insets: 0,1,4,5;
    -fx-background-radius: 9,8,5,4;
    -fx-padding: 15 30 15 30;
    -fx-font-family: "Helvetica";
    -fx-font-size: 18px;
    -fx-font-weight: bold;
    -fx-text-fill: #333333;
    -fx-effect: dropshadow( three-pass-box , rgba(255,255,255,0.2) , 1, 0.0 , 0 , 1);
}
#ipad-grey Text {
    -fx-effect: dropshadow( one-pass-box , white , 0, 0.0 , 0 , 1 );
}
#lion-default {
    -fx-background-color: 
        rgba(0,0,0,0.08),
        linear-gradient(#5a61af, #51536d),
        linear-gradient(#e4fbff 0%,#cee6fb 10%, #a5d3fb 50%, #88c6fb 51%, #d5faff 100%);
    -fx-background-insets: 0 0 -1 0,0,1;
    -fx-background-radius: 5,5,4;
    -fx-padding: 3 30 3 30;
    -fx-text-fill: #242d35;
    -fx-font-size: 14px;
}
#lion {
    -fx-background-color: 
        rgba(0,0,0,0.08),
        linear-gradient(#9a9a9a, #909090),
        linear-gradient(white 0%, #f3f3f3 50%, #ececec 51%, #f2f2f2 100%);
    -fx-background-insets: 0 0 -1 0,0,1;
    -fx-background-radius: 5,5,4;
    -fx-padding: 3 30 3 30;
    -fx-text-fill: #242d35;
    -fx-font-size: 14px;
}
#windows7-default {
    -fx-background-color: 
        #3c7fb1,
        linear-gradient(#fafdfe, #e8f5fc),
        linear-gradient(#eaf6fd 0%, #d9f0fc 49%, #bee6fd 50%, #a7d9f5 100%);
    -fx-background-insets: 0,1,2;
    -fx-background-radius: 3,2,1;
    -fx-padding: 3 30 3 30;
    -fx-text-fill: black;
    -fx-font-size: 14px;
}
#windows7 {
    -fx-background-color: 
        #707070,
        linear-gradient(#fcfcfc, #f3f3f3),
        linear-gradient(#f2f2f2 0%, #ebebeb 49%, #dddddd 50%, #cfcfcf 100%);
    -fx-background-insets: 0,1,2;
    -fx-background-radius: 3,2,1;
    -fx-padding: 3 30 3 30;
    -fx-text-fill: black;
    -fx-font-size: 14px;
}

 

반응형
반응형

IntelliJ에서 JavaFX 프로젝트 생성을 할 때 Maven 또는 Gradle 빌드환경을 선택하도록 되어있습니다. Gradle환경에서 외부 라이브러리 추가하는 방법에 대해 알아보겠습니다.

1. build.gradle 파일 수정

Gradle 환경으로 프로젝트를 생성하고 외부 Library를 추가할 때에는 build.gradle파일의 dependencies 부분에 인식시켜줘야 합니다.

<build.gradle>

dependencies {
    implementation files("libs/gson-2.9.0.jar") // 라이브러리 추가부분
    implementation files("libs/aquafx-0.1.jar") // 라이브러리 추가부분
    testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
    testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")
}

참고로 기존에 library 추가 명령은 compile, runtime, testCompile, testRuntime 이었으나, Gradle 4.10 (2018.8.27) 이래로 deprecate 되었습니다. 그리고 Gradle 7.0 (2021.4.9) 부터 삭제되었습니다. 삭제된 네 명령은 각각 implementation, runtimeOnly, testImplementation, testRuntimeOnly 으로 대체되었습니다. 아래와 같은 오류가 발생했다면 명령어를 다시 확인해봐야합니다.

Could not find method compile() for arguments [org.springframework:spring-context:5.0.2.RELEASE] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.

 


2. module-info.java 수정

module-info.java 파일에 해당 모듈도 추가를 해줘야 합니다.

반응형
반응형

1. main.java

package application;
	
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;


public class Main extends Application {
	@Override
	public void start(Stage primaryStage) {
		try {
			// fxml layout loader
//			FXMLLoader loader = new FXMLLoader();
//			loader.setLocation(getClass().getResource("MainView.fxml"));
//			// window root
//			BorderPane mainLayoutAnchorPane = (BorderPane) loader.load();
//			Scene scene = new Scene(mainLayoutAnchorPane);
//			scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
//			primaryStage.setScene(scene);
						
			Parent root = FXMLLoader.load(getClass().getResource("MainView.fxml"));			
			primaryStage.setScene(new Scene(root));
			
			primaryStage.setTitle("first javafx");			
			primaryStage.show();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		launch(args);
	}
}

2. MainView.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Rectangle?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>


<VBox fx:controller="application.Controller"  maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="500.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <StackPane prefHeight="150.0" prefWidth="380.0">
         <children>
            <Rectangle arcHeight="5.0" arcWidth="5.0" fill="#b8d2e4" height="120.0" stroke="BLACK" strokeType="INSIDE" width="300.0" />
            <Text fx:id="result" strokeType="OUTSIDE" strokeWidth="0.0" text="0" textAlignment="CENTER">
               <font>
                  <Font size="51.0" />
               </font>
            </Text>
         </children>
      </StackPane>
      <HBox alignment="TOP_CENTER" prefHeight="70.0" prefWidth="200.0">
         <children>
            <Button alignment="TOP_CENTER" minWidth="-Infinity" mnemonicParsing="false" prefHeight="60.0" prefWidth="60.0" text="7" textAlignment="CENTER" onAction="#operand">
               <font>
                  <Font size="27.0" />
               </font>
               <HBox.margin>
                  <Insets right="10.0" />
               </HBox.margin>
            </Button>
            <Button alignment="TOP_CENTER" minWidth="-Infinity" mnemonicParsing="false" prefHeight="60.0" prefWidth="60.0" text="8" textAlignment="CENTER" onAction="#operand">
               <font>
                  <Font size="27.0" />
               </font>
               <HBox.margin>
                  <Insets right="10.0" />
               </HBox.margin>
            </Button>
            <Button alignment="TOP_CENTER" minWidth="-Infinity" mnemonicParsing="false" prefHeight="60.0" prefWidth="60.0" text="9" textAlignment="CENTER" onAction="#operand">
               <font>
                  <Font size="27.0" />
               </font>
               <HBox.margin>
                  <Insets right="10.0" />
               </HBox.margin>
            </Button>
            <Button alignment="TOP_CENTER" minWidth="-Infinity" mnemonicParsing="false" prefHeight="60.0" prefWidth="60.0" text="/" textAlignment="CENTER" onAction="#operator">
               <font>
                  <Font size="27.0" />
               </font>
            </Button>
         </children>
         <VBox.margin>
            <Insets bottom="10.0" />
         </VBox.margin>
      </HBox>
      <HBox alignment="TOP_CENTER" prefHeight="70.0" prefWidth="200.0">
         <children>
            <Button alignment="TOP_CENTER" minWidth="-Infinity" mnemonicParsing="false" prefHeight="60.0" prefWidth="60.0" text="4" textAlignment="CENTER" onAction="#operand">
               <font>
                  <Font size="27.0" />
               </font>
               <HBox.margin>
                  <Insets right="10.0" />
               </HBox.margin>
            </Button>
            <Button alignment="TOP_CENTER" minWidth="-Infinity" mnemonicParsing="false" prefHeight="60.0" prefWidth="60.0" text="5" textAlignment="CENTER" onAction="#operand">
               <font>
                  <Font size="27.0" />
               </font>
               <HBox.margin>
                  <Insets right="10.0" />
               </HBox.margin>
            </Button>
            <Button alignment="TOP_CENTER" minWidth="-Infinity" mnemonicParsing="false" prefHeight="60.0" prefWidth="60.0" text="6" textAlignment="CENTER" onAction="#operand">
               <font>
                  <Font size="27.0" />
               </font>
               <HBox.margin>
                  <Insets right="10.0" />
               </HBox.margin>
            </Button>
            <Button alignment="TOP_CENTER" minWidth="-Infinity" mnemonicParsing="false" prefHeight="60.0" prefWidth="60.0" text="*" textAlignment="CENTER" onAction="#operator">
               <font>
                  <Font size="27.0" />
               </font>
            </Button>
         </children>
         <VBox.margin>
            <Insets bottom="10.0" />
         </VBox.margin>
      </HBox>
      <HBox alignment="TOP_CENTER" prefHeight="70.0" prefWidth="200.0">
         <children>
            <Button alignment="TOP_CENTER" minWidth="-Infinity" mnemonicParsing="false" prefHeight="60.0" prefWidth="60.0" text="1" textAlignment="CENTER" onAction="#operand">
               <font>
                  <Font size="27.0" />
               </font>
               <HBox.margin>
                  <Insets right="10.0" />
               </HBox.margin>
            </Button>
            <Button alignment="TOP_CENTER" minWidth="-Infinity" mnemonicParsing="false" prefHeight="60.0" prefWidth="60.0" text="2" textAlignment="CENTER" onAction="#operand">
               <font>
                  <Font size="27.0" />
               </font>
               <HBox.margin>
                  <Insets right="10.0" />
               </HBox.margin>
            </Button>
            <Button alignment="TOP_CENTER" minWidth="-Infinity" mnemonicParsing="false" prefHeight="60.0" prefWidth="60.0" text="3" textAlignment="CENTER" onAction="#operand">
               <font>
                  <Font size="27.0" />
               </font>
               <HBox.margin>
                  <Insets right="10.0" />
               </HBox.margin>
            </Button>
            <Button alignment="TOP_CENTER" minWidth="-Infinity" mnemonicParsing="false" prefHeight="60.0" prefWidth="60.0" text="-" textAlignment="CENTER" onAction="#operator">
               <font>
                  <Font size="27.0" />
               </font>
            </Button>
         </children>
         <VBox.margin>
            <Insets bottom="10.0" />
         </VBox.margin>
      </HBox>
      <HBox alignment="TOP_CENTER" prefHeight="70.0" prefWidth="200.0">
         <children>
            <Button alignment="TOP_CENTER" minWidth="-Infinity" mnemonicParsing="false" prefHeight="60.0" prefWidth="130.0" text="0" textAlignment="CENTER" onAction="#operand">
               <font>
                  <Font size="27.0" />
               </font>
               <HBox.margin>
                  <Insets right="10.0" />
               </HBox.margin>
            </Button>
            <Button alignment="TOP_CENTER" minWidth="-Infinity" mnemonicParsing="false" prefHeight="60.0" prefWidth="60.0" text="=" textAlignment="CENTER" onAction="#operator">
               <font>
                  <Font size="27.0" />
               </font>
               <HBox.margin>
                  <Insets right="10.0" />
               </HBox.margin>
            </Button>
            <Button alignment="TOP_CENTER" minWidth="-Infinity" mnemonicParsing="false" prefHeight="60.0" prefWidth="60.0" text="+" textAlignment="CENTER" onAction="#operator">
               <font>
                  <Font size="27.0" />
               </font>
            </Button>
         </children>
         <VBox.margin>
            <Insets bottom="10.0" />
         </VBox.margin>
      </HBox>
   </children>
</VBox>

 

3. Controller.java

package application;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.text.Text;

public class Controller {
	private String operator = "";
	private int x = 0; // 기존의 숫자
	private Model model = new Model();
	
	@FXML
	private Text result;

	@FXML
	private void operand(ActionEvent event) {
		result.setText(result.getText() + ((Button) event.getSource()).getText());
	}
	
	@FXML
	private void operator(ActionEvent event) {
		if(((Button) event.getSource()).getText().equals("=")) {
			result.setText(model.calculator(operator, x, Integer.parseInt(result.getText())) + "");;			
		} else {
			operator = ((Button) event.getSource()).getText();
			x = Integer.parseInt(result.getText());
			result.setText("");
		}
	}
}

4. Model.java

package application;

public class Model {
	
	public int calculator(String operator, int x, int y ) {
		if(operator.contentEquals("+")) {
			return x+y;
		}
		else if(operator.contentEquals("-")) {
			return x-y;
		}
		else if(operator.contentEquals("*")) {
			return x*y;
		}
		else {
			return x / y;
		}
	}
}

 

<결과>

반응형
반응형

1. JavaFX 플러그인 설치

경로: help > eclipse Marketplace

검색: javafx

 

2. JavaFX 라이브러리 설치

GlueON

 

JavaFX - Gluon

Roadmap Release GA Date Latest version Long Term Support Extended or custom support Details 19 September 2022 (planned) n/a no 18 March 2022 (planned) early access no 17 September 2021 17.0.0.1 (September 2021) until September 2026 upon request details 16

gluonhq.com

 

3. Scene Builder 설치

GlueON

 

Scene Builder - Gluon

Drag & Drop,Rapid Application Development. Download Now   Integrated Scene Builder works with the JavaFX ecosystem – official controls, community projects, and Gluon offerings including Gluon Mobile, Gluon Desktop, and Gluon CloudLink.   Simple Drag

gluonhq.com

 

4. 프로젝트 생성

경로: New > Other... > JavaFX Project

라이브러리 설정 : Build Path > Add External Archives > [JavaFX 다운로드 폴더/lib/ *.JAR파일만 선택]

 

5. 실행

반응형
반응형

인텔리제이에서 씬 빌더를 사용? 찾는 방법에 대해 적어놓습니다. 오랜만에 하려니 저도 어디있는지 까먹어서 많이 헷갈리네요...

 

처음 인텔리제이에서 javafx 프로젝트를 하나 생성하면 sample.fxml이라는 파일이 생성됩니다. fxml은 xml을 이용해 GUI를 쉽게 구현할 수 있게 해주는 언어인데요. 텍스트 탭과 scene builder 탭을 둘 다 볼 수 있습니다. 문제는 탭이 화면 아래쪽에 있는 것인데요....(아래 그림 참조)

이것때문에 괜히 파일명 우클릭해서 한참 찾았네요. 찾느라 고생 없으시길...

참고로, 처음 실행할 때 에러메시지와 함께 scene builder 다운로드가 아직 안됐다는 에러가 뜨는데... 해당 경고 따라 다운받아주시면 알아서 설치되고, 곧바로 보여집니다. 

 

scene builder가 보이는건 알겠고.... 헬로월드 한번 만들어보겠습니다.

간단히 Container-pane 하나 바탕에 마련해두고, Controls-Button 드래그-드랍으로 얹어 놓은 후에, 텍스트만 Hello로 바꿨습니다. 잘 뜨겠죠?

네, 잘 뜹니다. ㅋㅋㅋ.

조금 더 진행해보겠습니다. Hello Button 위쪽에 TextField를 갖다 놓습니다. 아직까지 ID 는 모두 지정하지 않은 상태입니다.

 

 

이제 Controller에 가서 객체드를 컨트롤 할 코드를 작성하도록 하겠습니다.

package sample;

import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.control.Alert.AlertType;

public class Controller {
    @FXML
    private TextField txtMsg;
    @FXML
    private Button btnAlert;

    public void clickHandler(){
        String msg = txtMsg.getText();

        Alert alert = new Alert(AlertType.INFORMATION);
        alert.setTitle("알림창");
        alert.setHeaderText(null);
        alert.setContentText(msg);

        alert.show();
    }
}

  

 그리고 이번엔 scenebuilder 화면으로 와서 할 작업이 있습니다. (참고로 저는 Intellij 내부 scene builder에서 아래 메뉴가 안보여서 별도로 설치한 Scene Builder를 통해서 열어 작업했습니다. sample.fxml 우클릭 후 open in scenebuilder)

1. 아래 화면 왼쪽의 Controller탭에서 Controller class를 방금 반들어준 sample.Controller가 되도록 선택해줍니다.

2. Button을 클릭한 상태로 우측 Code탭을 보시면 Identity 부분에서 ID를 골라줍니다. ID는 소스에서 작성한 변수명이 되겠습니다. txtMsg와 btnAlert 두가지가 보일텐데, 버튼에는 btnAlert, 텍스트필드에는 txtMsg를 각각 선택해줍니다.

3. Button의 On Action필드에는 코드에서 작성한 clickHandler를 선택해줍니다.

그럼 준비가 끝났습니다. 이제 실행해보겠습니다.

텍스트 필드에 적당한 텍스트를 쓰고, Hello 버튼을 누르면 알림창이 잘 뜹니다.

 

 

- 끝 -

반응형
반응형

1. JDK 설치

2. STS(Spring Tool Suit) 다운로드 및 설치

spring.io/tools 사이트로 이동하셔서 본인의 OS에 맞는 파일을 다운받아 설치합니다. 

최근에 실행파일이 .jar로 바뀐 것 같은데요... java가 깔려있다면 실행되며(압축풀림) 폴더 하나가 생기게 됩니다. 안되면 cmd에서 실행해야합니다. (java -jar 받은파일명.jar)

팁으로....탐색기의 경로에 cmd를 곧바로 치면 해당 폴더에서 커맨드가 열립니다.

 

폴더 안에 SpringToolSuite4.exe 실행파일을 실행하시면 설치없이 실행됩니다.

3. 프로젝트 생성

4. 폴더 구조

5. 파일 수정(DemoApplication.java)

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
public class DemoApplication {
	
	@RequestMapping("/")
	String home() {
		return "Hello World!";
	}
	
	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

}

6. 실행

- 끝 -

반응형
반응형

오늘은 Java GUI에서 테이블 출력을 구현하는 Swing의 JTable클래스를 활용하여, 간단한 예제를 구현하였습니다.

아래 코드를 실행하면 아래와 같은 화면이 나옵니다. 기능은 없고, 단순히 화면만 구성된 소스이니 참고하세요~~

 

 

package com;

import javax.swing.*;
import java.awt.*;

public class wij_com {
    public static void main(String args[]){

        Dimension dim = new Dimension(430, 400);  //단순 2차원값 입력을 위한 클래스

        JFrame frame = new JFrame("wij complex");
        frame.setLocation(0, 0);				  //출력 위치를 화면 좌상단에 위치
        frame.setPreferredSize(dim);              //위 코드에서 지정한 좌표를 프레임 사이즈로 사용
        frame.setLayout(null);                    //레이아웃을 사용하지 않고 절대좌표계 사용

        String header[]={"이름", "영어", "수학", "국어"};
        String contents[][]={
                {"이정현", "50", "60", "70"},
                {"김영호", "70", "80", "75"},
                {"전수용", "80", "65", "95"},
                {"김진희", "80", "65", "95"},
                {"신정섭", "85", "60", "85"},
                {"김승현", "80", "65", "95"},
                {"김영석", "80", "65", "95"},
                {"이정석", "80", "65", "95"},
                {"이승근", "80", "65", "95"},
        };

        JTable table = new JTable(contents, header);
        //table.setLocation(0,0);

        JScrollPane jscp1 = new JScrollPane(table); //이런식으로 생성시에 테이블을 넘겨주어야 정상적으로 볼 수 있다.
                                                    //jscp1.add(table); 과 같이 실행하면, 정상적으로 출력되지 않음.
        jscp1.setLocation(0,0);
        jscp1.setSize(300,160);

        frame.add(jscp1);

        Button jb = new Button("임시입력");
        jb.setLocation(10,230);
        jb.setSize(70,30);
        frame.add(jb);

        Button jb2 = new Button("임시출력");
        jb2.setLocation(80,230);
        jb2.setSize(70,30);
        frame.add(jb2);

        JLabel jl = new JLabel("SQL입력");
        jl.setLocation(10,270);
        jl.setSize(100,30);
        frame.add(jl);

        JTextField tf = new JTextField(10); // 텍스트필드 초기화
        tf.setLocation(10,300);
        tf.setSize(400,30);
        frame.add(tf);

        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //닫기버튼 클릭시 프로그램 종료

    }
}

(ps) 레이아웃/컨테이너를 책으로만 공부해서 아직 정확히 활용을 못하다보니 시행착오가 좀 있었는데, 생각보다 훨씬 힘들게...간신히 구현했네요. 다음엔 구성도 좀 더 Java스럽게 하는걸로...ㅋㅋ

 

-끝-

반응형

+ Recent posts