반응형

재귀적으로 처리하는 여러 예제가 있는데, AI한테 물어보니 간단한 방법을 알려줬다.

 

import org.apache.commons.io.FileUtils;

public class CopyDirectoryCommonsIO {
    public static void main(String[] args) throws IOException {
        Path source = Paths.get("C:/source/folder");
        Path target = Paths.get("C:/target/folder");

        FileUtils.copyDirectory(source.toFile(), target.toFile());
        System.out.println("폴더 복사 완료");
    }
}

 

 

반응형
반응형

 

위와 같이 프로젝트가 구성되있다고 할 때, pom.xml에 mybatis와 database driver를 설치해줍니다.

 

1. pom.xml (Maven기준)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>abc</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>javafx03_mybatis</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <junit.version>5.10.0</junit.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>17.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>17.0.6</version>
        </dependency>

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.microsoft.sqlserver/mssql-jdbc -->
        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>mssql-jdbc</artifactId>
            <version>12.4.2.jre11</version>
            <scope>runtime</scope>
        </dependency>
        <!-- MyBatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.10</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>0.0.8</version>
                <executions>
                    <execution>
                        <!-- Default configuration for running with: mvn clean javafx:run -->
                        <id>default-cli</id>
                        <configuration>
                            <mainClass>org.example.abc.HelloApplication</mainClass>
                            <launcher>app</launcher>
                            <jlinkZipName>app</jlinkZipName>
                            <jlinkImageName>app</jlinkImageName>
                            <noManPages>true</noManPages>
                            <stripDebug>true</stripDebug>
                            <noHeaderFiles>true</noHeaderFiles>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

 

2. module-info.java

스프링처럼 사용하려면 module-info.java 파일이 필요함. 아래의 추가부분을 설정해준다. (이 부분을 몰라서 한참 헤멤)

module org.example.abc {
    requires javafx.controls;
    requires javafx.fxml;
    requires java.sql;
    requires org.mybatis;  // <-- Add this

    opens org.example.abc to javafx.fxml;
    exports org.example.abc;
    exports org.example.abc.mapper;
    opens org.example.abc.mapper to javafx.fxml;
    exports org.example.abc.dto;
    opens org.example.abc.dto to javafx.fxml;
    opens mapper; // <-- 이거 추가해야 mapper 인식
}

 

3. MyBatisUtil.java

 

package org.example.abc;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class MyBatisUtil {
    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSessionFactory getSqlSessionFactory() {
        return sqlSessionFactory;
    }

    public static SqlSession getSession() {
        return sqlSessionFactory.openSession();
    }
}

 

4. mybatis-config.xml

특별한 건 없습니다. DB 접속정보를 적어주고, Mapper의 위치를 적어줍니다.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
                <property name="url" value="jdbc:sqlserver://<databaseURL>:<port_number>;databaseName=<DB>;encrypt=true;trustServerCertificate=true;"/>
                <property name="username" value="<username>"/>
                <property name="password" value="<password>"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/<매퍼이름>.xml"/>
    </mappers>
</configuration>

 

Mapper.xml 상세와 DTO, UI상세 등은 Spring과 동일함.

반응형
반응형
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
                <property name="url" value="jdbc:sqlserver://<주소>:<포트>;databaseName=<DB이름>;encrypt=true;trustServerCertificate=true;"/>
                <property name="username" value="이름"/>
                <property name="password" value="비밀번호"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/dbMapper.xml"/>
        <mapper resource="mapper/itemMapper.xml"/>
    </mappers>
</configuration>

 

encrypt=true;trustServerCertificate=true;

이 구문을 넣어줘야한다.

반응형
반응형

프로젝트 구조

 

1. 프로젝트 생성시 Mavin으로 생성

- pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>swing02_mybatis</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <!-- MyBatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.10</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc11 -->
        <dependency>
            <groupId>com.oracle.database.jdbc</groupId>
            <artifactId>ojdbc11</artifactId>
            <version>23.5.0.24.07</version>
        </dependency>

        <dependency>
            <groupId>com.oracle.ojdbc</groupId>
            <artifactId>orai18n</artifactId>
            <version>19.3.0.0</version>
        </dependency>
    </dependencies>
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

 

 

(ps) libs폴더에 테마를 위한 파일들을 넣어주고 "프로젝트 구조 > 종속 요소"에서 추가해준다. 개인적 취향...

idw-gpl.jar
0.70MB
JTattoo.jar
0.62MB
liquidlnf.jar
0.35MB
ojdbc6-11.2.0.4.jar
2.61MB
quaqua.jar
1.94MB

 

 

2. mybatis-config.xml에서 DB정보 생성

 

3. org.example.mapper > dbMapper 인터페이스 생성

package org.example.mapper;

import org.example.model.dbModel;
import java.util.List;

public interface dbMapper {
    List<dbModel> selectAll();
}

 

4. org.example.dto> dbDto생성 (레코드 형식이 편해서 클래스 대신 레코드를 주로 사용함)

package org.example.dto;

public record dbDto(
        String emp_no,
        String emp_x,
        String kornm_n,
        String hannm_n,
        String engnm_n,
        String res
) {
}

 

5. MyBatisUtil 생성

package org.example;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class MyBatisUtil {
    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSessionFactory getSqlSessionFactory() {
        return sqlSessionFactory;
    }

    public static SqlSession getSession() {
        return sqlSessionFactory.openSession();
    }
}

 

 

6. service > DbService 생성

DAO를 생성하는 경우가 많이 있는 것 같은데, 개인적으로는 복잡도가 낮아서 service만 만들어 구현해도 큰 어려움이 없는것 같다. DAO에 대한 개념도 없는 상태라, 프로젝트의 복잡도만 늘리는 것 같아서 Service만 구현했다.

package org.example.service;

import org.apache.ibatis.session.SqlSession;
import org.example.MyBatisUtil;
import org.example.dto.dbDto;
import org.example.mapper.dbMapper;

import java.util.List;

public class DbService {
    public List<dbDto> selectAll(){
        SqlSession session = MyBatisUtil.getSession();
        List<dbDto> list = null;

        try{
            dbMapper mapper = session.getMapper(dbMapper.class);
            list = mapper.selectAll();
        } catch (Exception ex){
            ex.printStackTrace();
        } finally {
            session.close();
        }
        return list;
    }
}

 

 

7. resources > mapper > dbMapper.xml 생성

Spring에서 사용하던 Mybatis와 동일하게 생성

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.example.mapper.dbMapper">
    <select id="selectAll" resultType="org.example.model.dbModel">
        select emp_# as emp_no,
        emp_x,
        kornm_n,
        hannm_n,
        engnm_n,
        res_#1 as res
        from temp a
        where a.kornm_n='김동개'
    </select>
</mapper>

 

8. org.example.view > MainView.java 생성

package org.example.view;

import org.example.dto.dbDto;
import org.example.service.DbService;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;

public class MainView extends JFrame {
        DbService dbService = new DbService();

        JFrame f1 =new JFrame();    // Main Frame
        JMenuBar mb = new JMenuBar(); // 메뉴바
        JPanel sidePanel = new JPanel(); // 사이드 패널
        JPanel contentPanel = new JPanel(); // 컨텐츠 패널
        JPanel footerPanel = new JPanel();  // 푸터 패널
        JButton jb1 = new JButton("search"); // 버튼 초기화
        JButton jb2 = new JButton("insert"); // 버튼 초기화
        JButton jb3 = new JButton("delete"); // 버튼 초기화

//      JTable data_table = new JTable(); //테이블 생성시에는 초기값과 헤더를 넣어줘야한다. 
//        이 작업은 초기 화면 생성하는 함수에 넣어주기 위해, 아래와 같이 null로 우선 생성한다.
        JTable data_table = null;

        public void set_style(Component target){
            // 스타일 적용(Look & Feel)
            try{
                UIManager.setLookAndFeel ("com.birosoft.liquid.LiquidLookAndFeel"); 	//Liquid
            }catch(Exception e){
                System.out.println(e + "오류 발생");
            }
            SwingUtilities.updateComponentTreeUI(target) ;
        }

        public void createFrame(){
            // Main Frame 세팅
            f1.setSize(1024,760);//크기
            f1.setDefaultCloseOperation(f1.EXIT_ON_CLOSE);
            f1.setLocationRelativeTo(null);

            // 스타일 적용
            f1.setDefaultLookAndFeelDecorated(true);
            set_style(f1);

            // 아이콘 적용
            Image icon = Toolkit.getDefaultToolkit().getImage("D:\\7_System_dev2\\4_Java\\01_gui\\src\\icon.png");
            f1.setIconImage(icon);

            // 레이아웃 적용
            BorderLayout bl = new BorderLayout();
            f1.setLayout(bl);

            // 화면 요소 생성 및 추가
            createMenu();
            createSidePanel();
            createContentPanel();
            createFooter();

            f1.add(mb, BorderLayout.NORTH);
            f1.add(sidePanel, BorderLayout.WEST);       // f1라는 프레임에 sidePanel추가
            f1.add(contentPanel, BorderLayout.CENTER);  // f1라는 프레임에 contentPanel추가
            f1.add(footerPanel, BorderLayout.SOUTH);    // f1라는 프레임에 FooterPanel추가

            f1.setTitle("Frame Test");//제목
            f1.setVisible(true);//생성
        }

        // 메뉴바
        public void createMenu(){
            JMenu fileMenu = new JMenu("File");
            fileMenu.add(new JMenuItem("New"));
            fileMenu.add(new JMenuItem("Open"));
            fileMenu.add(new JMenuItem("Preferences"));

            mb.add(fileMenu);
            mb.add(new JMenu("Edit"));
            mb.add(new JMenu("About"));
            mb.add(new JMenu("Help"));
            setJMenuBar(mb);
        }

        // 사이드 패널
        public void createSidePanel(){
            sidePanel.setPreferredSize(new Dimension(100, 300)); // 사이드패널 사이즈 조절
            sidePanel.setBorder(BorderFactory.createEmptyBorder(15 , 10, 10 , 10));
//            sidePanel.setLayout(new BoxLayout(sidePanel, BoxLayout.Y_AXIS));

            sidePanel.add(jb1);
            sidePanel.add(jb2);
            sidePanel.add(jb3);

            set_style(sidePanel);

            jb1.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    data_mapping();

                    // 패널 갱신
                    contentPanel.revalidate();
                    contentPanel.repaint();
                }
            });
        }

        // Contents 패널
        public void createContentPanel(){
            contentPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
            contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS));
            JLabel Headline = new JLabel("Swing Table Data with Styles");
            Font f = new Font("고딕", Font.BOLD,20);
            Headline.setFont(f);
            contentPanel.add(Headline);

            // 테이블 준비
            String[] header = {"EMP No", "Name"};
            String[][] contents = {{"",""},{"",""},{"",""}};
            data_table = new JTable(contents, header);
            Font font = new Font("고딕", Font.PLAIN,12);
            data_table.setFont(font);
            contentPanel.add(new JScrollPane(data_table), BorderLayout.CENTER);
			// JScrollPane(data_table)에 넣어주지 않으면 header가 나타나지 않는다.
            set_style(contentPanel);
        }

        // Footer
        public void createFooter(){
            footerPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
            footerPanel.setBackground(Color.orange);
            JLabel Footer = new JLabel("Copyright by Wilkyway");
            footerPanel.add(Footer);

            // set_style(footerPanel);
        }

        public void data_mapping() {
            List<dbDto> models = dbService.selectAll();

            int i=0;
            for (dbDto model : models) {
                System.out.println("ID: " + model.emp_no() + ", Name: " + model.kornm_n());
                data_table.setValueAt(model.emp_no(),i,0);
                data_table.setValueAt(model.kornm_n(),i,1);
                i++;
            }
        }

}

 

 

8. Main.java

package org.example;
import org.example.view.MainView;

public class Main {

    public static void main(String[] args) {
        MainView mp = new MainView();
        mp.createFrame();
    }
}

 

 

<결과>

반응형
반응형

 인텔리제이(Intellij) IDE 를 사용하여 간단한 텍스트 에디터를 만들어보도록 하겠습니다.

 

1. 새 프로젝트 생성

인텔리제이 메뉴에서 File - New - Project 를 클릭하여 새 프로젝트를 생성해줍니다. Name은 editor로 하고, 적당한 위치에 아래와 같은 세팅으로 진행할 예정입니다. JDK는 설치되어있지 않다면 JDK의 드롭다운 메뉴 중 Download JDK를 눌러, 적당한 버전을 고른 후 다운로드 받아줍니다. 혹은 직접 원하는 JDK를 다운로드 받아서 선택할 수도 있습니다.

2. Main Class 생성

프로젝트 하위 폴더 중 src에서 우클릭하여 New - Java Class 를 클릭한 후, 클래스 이름을 editor로 하여 새로운 클래스를 생성해줍니다. 

만들어진 클래스 내부에 프로그램 진입점인 main함수를 만들어서 테스트해보겠습니다.

public class editor {
    public static void main(String[] args){
        System.out.println("Hello world");
    }
}

3. Build & Run

Build - Build Project를 눌러 프로젝트를 빌드해줍니다. (최초에는 Run 메뉴가 아직 활성화되지 않았습니다. 한번만 Build해주면, 다음부터는 Run만해도 자동으로 Build까지 수행해줍니다.)

다음으로 Run해줍니다. 그리고 editor라고 되어있는 메뉴를 클릭합니다.

콘솔에 Hello world가 잘 나옵니다.

4. GUI 프로그램 코드

아래의 코드를 복사하여 실행이 되는지 확인해봅니다.

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


public class editor extends JFrame implements ActionListener {

    JTextArea t;
    JFrame f;

    // Constructor
    editor(){
        f = new JFrame("editor");
        f.setDefaultCloseOperation(f.EXIT_ON_CLOSE);
        
        // 테마 설정
        try{
            UIManager.setLookAndFeel("com.birosoft.liquid.LiquidLookAndFeel");
        } catch (Exception e) {
            System.out.println(e + "오류 발생");
        }
                
        t = new JTextArea(); // 텍스트 편집창
        JMenuBar mb = new JMenuBar(); // 메뉴바

        JMenu m1 = new JMenu("File"); //메뉴1
        JMenuItem mi1 = new JMenuItem("New"); //메뉴 아이템1
        JMenuItem mi2 = new JMenuItem("Open"); //메뉴 아이템2
        JMenuItem mi3 = new JMenuItem("Save"); //메뉴 아이템3
        JMenuItem mi9 = new JMenuItem("Print"); //메뉴 아이템4
        mi1.addActionListener(this);
        mi2.addActionListener(this);
        mi3.addActionListener(this);
        mi9.addActionListener(this);
        m1.add(mi1);
        m1.add(mi2);
        m1.add(mi3);
        m1.add(mi9);

        JMenu m2 = new JMenu("Edit");	// 메뉴2
        JMenuItem mi4 = new JMenuItem("cut"); //메뉴 2-1
        JMenuItem mi5 = new JMenuItem("copy");//메뉴 2-2
        JMenuItem mi6 = new JMenuItem("paste");//메뉴 2-3
        mi4.addActionListener(this);
        mi5.addActionListener(this);
        mi6.addActionListener(this);
        m2.add(mi4);
        m2.add(mi5);
        m2.add(mi6);

        JMenuItem mc = new JMenuItem("close"); // 메뉴3
        mc.addActionListener(this);

        mb.add(m1);
        mb.add(m2);
        mb.add(mc);

        f.setJMenuBar(mb);
        f.add(t);
        f.setSize(500, 500);
        f.show();


    }

	// 각 클릭 이벤트에 대한 기능 정의
    @Override
    public void actionPerformed(ActionEvent e) {
        String s = e.getActionCommand();

        if (s.equals("cut")){
            t.cut();
        } else if (s.equals("copy")){
            t.copy();
        } else if(s.equals("paste")){
            t.paste();
        } else if (s.equals("Save")){
            JFileChooser j = new JFileChooser("f:");

            int r = j.showSaveDialog(null);

            if (r == JFileChooser.APPROVE_OPTION){
                File fi = new File(j.getSelectedFile().getAbsolutePath());
                try {
                    FileWriter wr = new FileWriter(fi, false);
                    BufferedWriter w = new BufferedWriter(wr);
                    w.write(t.getText());

                    w.flush();
                    w.close();
                } catch (Exception evt){
                    JOptionPane.showMessageDialog(f, evt.getMessage());
                }
            } else JOptionPane.showMessageDialog(f, "the user cancelled the operation");
        } else if (s.equals("Print")) {
            try {
                t.print();
            } catch (Exception evt) {
                JOptionPane.showMessageDialog(f, evt.getMessage());
            }
        } else if (s.equals("Open")){
            JFileChooser j = new JFileChooser("f:");
            int r = j.showOpenDialog(null);
            if (r == JFileChooser.APPROVE_OPTION){
                File fi = new File(j.getSelectedFile().getAbsolutePath());

                try {
                    String s1 = "", sl = "";
                    FileReader fr = new FileReader(fi);
                    BufferedReader br = new BufferedReader(fr);

                    sl = br.readLine();

                    while((s1 = br.readLine()) != null){
                        sl = sl + "\n" + s1;
                    }
                    t.setText(sl);
                } catch(Exception evt){
                    JOptionPane.showMessageDialog(f, evt.getMessage());

                }
            } else JOptionPane.showMessageDialog(f, "the user canced the operation");
        }
        else if (s.equals("New")){
            t.setText("");
        } else if(s.equals("close")){
//            f.setVisible(false);
            System.exit(0);
        }
    }

    public static void main(String[] args) {

        editor e = new editor();
    }
}

 

 

5. 테마 적용

프로젝트(editor) 에서 우클릭 후 New- Directory를 클릭하고, 폴더 이름을 libs로 하여 새 폴더를 생성합니다.

생성된 폴더에 제가 애용하는 liquid 테마를 복사해 넣습니다. 해당 테마(라이브러리)는 첨부 참조하시기 바랍니다.

liquidlnf.jar
0.35MB

폴더를 보면 liquidlnf.jar파일이 추가되어 있는 것이 보입니다. libs폴더를 우클릭 후, Add as Library...를 클릭, OK 클릭하면 해당 폴더의 라이브러리들이 자동으로 프로젝트 라이브러리 리스트에 추가됩니다.

실행해보면 liquid 테마가 들어간 프로그램이 실행되는 모습을 볼 수 있습니다. (버튼이 많아야 좀 더 화려한데...)

 

이상으로 간단한 텍스트 에디터를 Swing으로 만들어보았습니다.

 

~~끝~~

반응형
반응형

 

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 파일에 해당 모듈도 추가를 해줘야 합니다.

반응형

+ Recent posts