<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      開源項(xiàng)目YtyMark文本編輯器--UI界面相關(guān)功能(關(guān)于設(shè)計(jì)模式的實(shí)戰(zhàn)運(yùn)用)

      ??開源項(xiàng)目地址

      ?? GitHub 開源地址(YtyMark-java)

      歡迎提交 PR、Issue、Star ??!

      ??1. 簡(jiǎn)述

      YtyMark-java項(xiàng)目分為兩大模塊:

      • UI界面(ytyedit-mark)

      • markdown文本解析和渲染(ytymark)

      本文主要內(nèi)容為UI界面相關(guān)功能。

      關(guān)于markdown文本解析器UI界面的實(shí)現(xiàn)。在這整個(gè)流程中,如果通過(guò)設(shè)計(jì)模式實(shí)現(xiàn)高內(nèi)聚低耦合,可重用,易于閱讀,易于擴(kuò)展,易于維護(hù)等。

      YtyMark-java
      ├── ytyedit-mark/
      │   ├── src/
      │   │   ├── main/
      │   │   │   ├── java/
      │   │   │   │   ├── editor/             # JavaFX UI 界面
      │   │   │   │   ├── enums/              # Icon圖標(biāo)等
      │   │   │   │   ├── utils/              # 資源讀取等
      │   │   │   │   ├── window/             # 自定義窗口(主窗口、彈框)
      │   │   │   │   ├── RenderMarkdown      # 解析和渲染
      │   │   │   │   ├── YtyEditApplication  # 主程序入口
      │   │   │   └── resources/
      │   │   │       └── css/                # 主題樣式(CSS)
      │   │   │       └── fonts/              # 字體集
      │   │   │       └── images/             # 圖片
      │   ├── README.md
      │   └── pom.xml
      

      ??2. JavaFX 用戶界面

      目標(biāo):為用戶提供可視化的文本輸入、實(shí)時(shí)預(yù)覽、編輯、保存、導(dǎo)出(PDF/HTML)和主題切換等功能。

      使用到的設(shè)計(jì)模式

      • 工廠模式樣式的創(chuàng)建通過(guò)工廠模式來(lái)完成。

      • 策略模式:動(dòng)態(tài)選擇工具界面樣式,完成UI界面的樣式切換。

      • 觀察者模式:識(shí)別到主題發(fā)生變化時(shí)執(zhí)行重新渲染操作;樣式切換后,渲染的文字樣式也需要同步調(diào)整,再結(jié)合監(jiān)聽器(觀察者模式)來(lái)實(shí)現(xiàn)主題變化后重新渲染文本內(nèi)容,除此之外JavaFX使用了大量的監(jiān)聽器。

      • 單例模式:主題樣式管理器統(tǒng)一管理全局樣式,并提供統(tǒng)一訪問(wèn)入口。

      • 裝飾模式:對(duì)自定義基礎(chǔ)彈框做定制化的擴(kuò)展,實(shí)現(xiàn)不同場(chǎng)景所需的彈框。

      • 命令模式:封裝工具界面中的功能點(diǎn)及快捷鍵命令。

      • 備忘錄模式:負(fù)責(zé)實(shí)現(xiàn)撤銷恢復(fù)功能,實(shí)現(xiàn)精細(xì)到單字符的撤銷/恢復(fù)機(jī)制。

      2.1. 工廠模式

      通過(guò)工廠創(chuàng)建樣式,將默認(rèn)的樣式創(chuàng)建好,統(tǒng)一放入Map中保存,需要時(shí)直接從工廠中獲取。

      public class StyleFactory {
          private static final Map<Key, Style> STYLE_MAP = new HashMap<>();
      
          // 預(yù)先注冊(cè)默認(rèn)樣式
          static {
              registerStyle(WindowType.MAIN_WINDOW, ThemeType.LIGHT, new MainWindowLightStyle());
              registerStyle(WindowType.MAIN_WINDOW, ThemeType.DARK, new MainWindowDarkStyle());
              registerStyle(WindowType.DIALOG_WINDOW, ThemeType.LIGHT, new DialogWindowLightStyle());
              registerStyle(WindowType.DIALOG_WINDOW, ThemeType.DARK, new DialogWindowDarkStyle());
          }
      
          public static void registerStyle(WindowType type, ThemeType theme, Style style) {
              STYLE_MAP.put(new Key(type, theme), style);
          }
      
          public static Style getStyle(WindowType type, ThemeType theme) {
              Style style = STYLE_MAP.get(new Key(type, theme));
              if (style == null) {
                  throw new RuntimeException("窗口類型或主題類型不支持: " + type + " - " + theme);
              }
              return style;
          }
      
          ...
      }
      

      2.2. 策略模式

      動(dòng)態(tài)選擇工具界面樣式,完成UI界面的樣式切換。并支持對(duì)已有窗口樣式的自由組合,比如深色的主窗口+淺色的彈框。

      使用setTheme(ThemeType)方法可以快速切換已經(jīng)搭配好的主題;使用setStyle可以靈活指定不同窗口的樣式。

      public class ThemeContext {
          ...
      
          // 設(shè)置樣式
          public void setTheme(ThemeType theme) {
              WindowType[] values = WindowType.values();
              for (WindowType windowType : values) {
                  this.themeManager.setStyle(windowType, theme);
              }
          }
      
          // 自定義設(shè)置不同窗體不同樣式
          public void setStyle(WindowType type, ThemeType theme) {
              this.themeManager.setStyle(type, theme);
          }
      
          // 主題切換
          public void switchTheme() {
              // 清空之前的樣式
              scene.getStylesheets().clear();
              this.themeManager.applyStyle(WindowType.MAIN_WINDOW, scene);
          }
      
      }
      

      2.3. 觀察者模式和單例模式

      識(shí)別到主題發(fā)生變化時(shí)執(zhí)行重新渲染操作。樣式切換后,渲染的文字樣式也需要同步調(diào)整,結(jié)合監(jiān)聽器(觀察者模式)來(lái)實(shí)現(xiàn)主題變化后重新渲染文本內(nèi)容,除此之外JavaFX使用了大量的監(jiān)聽器。

      自定義的主題監(jiān)聽器接口:

      public interface ThemeChangeListener {
          void onThemeChanged();
      }
      

      主題監(jiān)聽器將有主題管理類來(lái)統(tǒng)一管理,并結(jié)合單例模式,使得主題管理器全局唯一,并提供統(tǒng)一訪問(wèn)入口ThemeManager.getInstance()。

      public class ThemeManager {
      
          private static ThemeManager instance;
          private final Map<WindowType, Style> currentStyles = new HashMap<>();
          private final List<ThemeChangeListener> listeners = new ArrayList<>();
      
      
          private ThemeManager() {
              // 默認(rèn)主窗口白天模式,彈窗白色模式
              currentStyles.put(WindowType.MAIN_WINDOW, new MainWindowLightStyle());
              currentStyles.put(WindowType.DIALOG_WINDOW, new DialogWindowLightStyle());
          }
      
          public static ThemeManager getInstance() {
              if (instance == null) {
                  instance = new ThemeManager();
              }
              return instance;
          }
      
          public void setStyle(WindowType type, ThemeType theme) {
              currentStyles.put(type, StyleFactory.getStyle(type, theme));
              // 通知所有觀察者主題已變更
              this.notifyThemeChanged();
          }
      
          ...
      
          // 注冊(cè)觀察者
          public void addThemeChangeListener(ThemeChangeListener listener) {
              listeners.add(listener);
          }
          // 注銷觀察者
          public void removeThemeChangeListener(ThemeChangeListener listener) {
              listeners.remove(listener);
          }
      
          // 通知所有觀察者
          private void notifyThemeChanged() {
              for (ThemeChangeListener listener : listeners) {
                  listener.onThemeChanged();
              }
          }
      }
      

      通用彈框渲染處理類實(shí)現(xiàn)了監(jiān)聽器接口,在創(chuàng)建時(shí)注冊(cè)到監(jiān)聽器中

      public class GenericDialog implements ThemeChangeListener {
      
          public GenericDialog(Stage owner) {
              ...
      
              this.themeManager.addThemeChangeListener(this);
      
              ...
          }
      
          /**
           * 訂閱主題樣式變更,主題變更后自動(dòng)切換彈窗樣式
           */
          @Override
          public void onThemeChanged() {
              // 清空之前的樣式
              dialogScene.getStylesheets().clear();
              themeManager.applyStyle(WindowType.DIALOG_WINDOW,dialogScene);
          }
      }
      

      渲染處理類監(jiān)聽相關(guān)源碼

      public class RenderMarkdown  implements ThemeChangeListener {
          public RenderMarkdown(Tab tab) {
              ...
      
              // 注冊(cè)自己為 ThemeContext 的監(jiān)聽者
              ThemeManager.getInstance().addThemeChangeListener(this);
      
              ...
          }
          /**
           * 訂閱主題樣式變更,主題變更后自動(dòng)重新渲染內(nèi)容
           */
          @Override
          public void onThemeChanged() {
              // 主題變更后自動(dòng)渲染
              renderMarkdown(null);
          }
      }
      

      2.4. 裝飾模式

      對(duì)自定義基礎(chǔ)彈框做定制化的擴(kuò)展,實(shí)現(xiàn)不同場(chǎng)景所需的彈框。彈框裝飾類通過(guò)組合的方式,對(duì)通用彈框做定制化設(shè)置

      public abstract class DialogDecorator {
          private GenericDialog dialog;
      
          public DialogDecorator(GenericDialog dialog) {
              this.dialog = dialog;
          }
      
          public void removeLogo(boolean flag){
              dialog.removeLogo(flag);
          }
          // 委托設(shè)置標(biāo)題
          public void setTitle(String title) {
              dialog.setTitle(title);
          }
      
          // 委托設(shè)置主體內(nèi)容
          public void setContent(Node content) {
              dialog.setContent(content);
          }
      
          // 委托添加內(nèi)容
          public void addContent(Node node) {
              dialog.addContent(node);
          }
      
          // 委托設(shè)置底部按鈕區(qū)域
          public void setFooter(Node node) {
              dialog.setFooter(node);
          }
      
          // 委托添加底部按鈕
          public void addFooter(Node node) {
              dialog.addFooter(node);
          }
      
          // 顯示并阻塞,返回用戶操作結(jié)果
          public void showAndWait() {
              dialog.showAndWait();
          }
      
      }
      

      2.5. 命令模式和備忘錄模式

      封裝工具界面中的功能點(diǎn)及快捷鍵命令。備忘錄模式負(fù)責(zé)實(shí)現(xiàn)撤銷恢復(fù)功能,實(shí)現(xiàn)精細(xì)到單字符的撤銷/恢復(fù)機(jī)制,主要涉及的類:管理文本狀態(tài)TextEditorOriginator、管理撤銷和恢復(fù)的棧UndoRedoCaretaker

      public class UndoRedoCaretaker {
      
          private Deque<TextMemento> undoStack = new ArrayDeque<>();
          private Deque<TextMemento> redoStack = new ArrayDeque<>();
          private TextEditorOriginator originator;
          private boolean isUndoRedo = false;
          private static final int MAX_HISTORY = 1000; // 最多保存 1000 步
      
          public UndoRedoCaretaker(TextEditorOriginator originator) {
              this.originator = originator;
              // 存入初始狀態(tài),確保撤銷可用
              undoStack.push(originator.save());
          }
      
          // 保存
          public void saveState(String text, int caretPosition) {
             ...
          }
      
          // 撤銷
          public void undo() {
              ...
          }
          // 恢復(fù)
          public void redo() {
              ...
          }
          public boolean isUndoRedo() {
              return isUndoRedo;
          }
          public void clear() {
              undoStack.clear();
              redoStack.clear();
          }
      
      }
      

      ?? 3. 界面截圖預(yù)覽

      白天模式的截圖:

      image

      夜間模式的截圖:

      image

      ??4. 總結(jié)

      YtyMark 編輯器界面UI相關(guān)功能,將多種設(shè)計(jì)模式融入到實(shí)際應(yīng)用中,從實(shí)踐中積累程序設(shè)計(jì)經(jīng)驗(yàn)。

      更多詳細(xì)內(nèi)容可以前往筆者微信公眾號(hào)回復(fù):設(shè)計(jì)模式,來(lái)獲取,后續(xù)有關(guān)設(shè)計(jì)模式的新資料都可以從這個(gè)入口獲取到。

      • 秘籍1設(shè)計(jì)模式手冊(cè):《掌握設(shè)計(jì)模式:23種經(jīng)典模式實(shí)踐、選擇、價(jià)值與思想》

      • 秘籍2練手項(xiàng)目:設(shè)計(jì)模式實(shí)戰(zhàn)項(xiàng)目--markdown文本編輯器軟件開發(fā)(已開源

      image

      查看往期設(shè)計(jì)模式文章的:設(shè)計(jì)模式

      超實(shí)用的SpringAOP實(shí)戰(zhàn)之日志記錄

      2023年下半年軟考考試重磅消息

      通過(guò)軟考后卻領(lǐng)取不到實(shí)體證書?

      計(jì)算機(jī)算法設(shè)計(jì)與分析(第5版)

      Java全棧學(xué)習(xí)路線、學(xué)習(xí)資源和面試題一條龍

      軟考證書=職稱證書?

      軟考中級(jí)--軟件設(shè)計(jì)師毫無(wú)保留的備考分享

      三連支持!!!

      posted @ 2025-04-23 07:43  淵渟岳  閱讀(498)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 成人欧美日韩一区二区三区| 亚洲精品不卡无码福利在线观看| 亚洲第一国产综合| 亚洲午夜精品国产电影在线观看| 国产女主播一区| 欧美乱妇高清无乱码免费| 国产伦视频一区二区三区| 精品一区二区中文字幕| 国产中文三级全黄| 免费人成年激情视频在线观看| 日韩理伦片一区二区三区| 午夜福利理论片高清在线| 日韩一区二区三区日韩精品| 国产蜜臀精品一区二区三区| 精品一区二区三区在线观看l| 日韩伦理片| 视频一区视频二区卡通动漫| 被灌满精子的少妇视频| 日日碰狠狠躁久久躁96avv | 丰满无码人妻热妇无码区| 肉大榛一进一出免费视频| 99久久精品国产综合一区| 久久国产免费观看精品3| 舞钢市| 国内自拍第一区二区三区| 人妻精品动漫H无码中字| 亚洲成人资源在线观看| 国产mv在线天堂mv免费观看| 亚洲精品网站在线观看不卡无广告 | A级孕妇高清免费毛片| 中文字幕av无码免费一区| 美女一区二区三区在线观看视频| 亚洲欧美人成电影在线观看| 无码专区 人妻系列 在线| 亚洲国产av一区二区| 97精品人妻系列无码人妻 | 97国产成人无码精品久久久| 三上悠亚精品二区在线观看| 国产精品视频亚洲二区| 日韩卡一卡2卡3卡4卡| 97久久久亚洲综合久久|