国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

自制字幕遮擋器

zqhxuyuan / 2793人閱讀

摘要:實(shí)際上,如果百度字幕遮擋器,很可以找到一些結(jié)果,但多半是不透明的,不符合我的使用需要,再者自己寫這種小工具是很有趣的學(xué)習(xí)過程。

實(shí)際上,如果百度“字幕遮擋器,很可以找到一些結(jié)果,但多半是不透明的,不符合我的使用需要,再者自己寫這種小工具是很有趣的學(xué)習(xí)過程。這個(gè)學(xué)習(xí)過程中有一些心得,不得不記錄一二。

程序用途

對(duì)字幕進(jìn)行遮擋(學(xué)習(xí)英語用)

在網(wǎng)頁中對(duì)一段文字加上底色,提高閱讀時(shí)的注意力程度(個(gè)人需求)

兩種用途如下圖所示

功能要求

根據(jù)程序的用途可以看出,該程序必須實(shí)現(xiàn)以下功能:

半透明窗體

總在最前

大小調(diào)整

拖動(dòng)

關(guān)閉

后三個(gè)功能實(shí)際上都是因?yàn)闊o標(biāo)題,所以需要自己實(shí)現(xiàn)。此外,還有一些錦上添花的功能:

顏色選擇(包括不透明度的調(diào)節(jié))

切換是否總在最前

記憶顏色與位置

防止窗口縮得過小而無法找到

后來在編程實(shí)現(xiàn)的過程中也會(huì)按這些功能來描述。

編程實(shí)現(xiàn)

語言: Java

程序的功能并不復(fù)雜,因此結(jié)構(gòu)上也偷了些懶。一個(gè)主類Cover,其中調(diào)用起繼承自JFrameCoverFrame
這里都是一些很定式的寫法,沒什么特別的

public class Cover {
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                CoverFrame frame = new CoverFrame();
                ...
            }
        });
    }
}

class CoverFrame extends JFrame {
    ...
}

程序的各項(xiàng)主要功能基本上是在CoverFrame中實(shí)現(xiàn)的,具體將在后文一一敘述。

半透明窗體

半透明窗體的關(guān)鍵是先要去掉窗體的標(biāo)題和邊框,然后給該Frame設(shè)置半透明背景色即可。

class CoverFrame extends JFrame {
    ...
    private Color color = new Color(0, 0, 0, 200);  //半透明
    ...

    public CoverFrame() {
        ...
        setUndecorated(true);  //去掉邊框
        ...
        setBackground(color);
        ...
        getContentPane().setBackground(color);
        }
}

這部分比較簡單,不過值得一說的是,如果窗體將保持半透明,即窗體不會(huì)被設(shè)置成不透明色的話(因?yàn)楹竺婕尤肓祟伾x擇,用戶完全可能選擇完全不透明的顏色),只要對(duì)CoverFrame對(duì)象setBackground(color)即可。
但一旦選擇了完全不透明的顏色(Alpha值為255),窗口則會(huì)變?yōu)槟J(rèn)的灰色。避免這種情況,就需要把Frame的ContentPane也設(shè)置成相同顔色getContentPane().setBackground(color)

總在最前

想要窗體總在最前也比較簡單,有一個(gè)現(xiàn)成的函數(shù)setAlwaysOnTop來控制。要讓程序能切換是否總在最前,也只要在CoverFrame中設(shè)置一個(gè)布爾型的state,作為是否總在最前的開關(guān),并添加一個(gè)JCheckBoxMenuItem到窗口的JPopupMenu中去。

class CoverFrame extends JFrame {
    ...
    private JPopupMenu popupMenu = new JPopupMenu();   //右鍵菜單 
    private Color color = new Color(0, 0, 0, 200);
    private boolean onTop = true;  //默認(rèn)總在最前
    ...

    public CoverFrame() {
        setAlwaysOnTop(onTop);
        ...
        CoverFrame that = this;


        // set up popup menus
        ...
        JMenuItem topItem = new JCheckBoxMenuItem("Always On Top", true);  //帶勾選框,默認(rèn)勾選
        topItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                onTop = !onTop; 
                setAlwaysOnTop(onTop);  //改變當(dāng)前狀態(tài)
            }
        });
        popupMenu.add(topItem);
        ...
    }
}
拖動(dòng)與大小調(diào)整

這兩個(gè)功能本來應(yīng)該是一個(gè)窗體固有的,但因?yàn)榘褬?biāo)題與邊框都去掉了,現(xiàn)在都需要自己來實(shí)現(xiàn)。因?yàn)閮蓚€(gè)功能的代碼犬牙交錯(cuò),所以放在一起來講了。
拖動(dòng)的原理是,點(diǎn)擊時(shí)記錄點(diǎn)擊位置(相對(duì)于窗口原點(diǎn)),拖動(dòng)時(shí)獲得鼠標(biāo)在屏幕上的絕對(duì)位置,這一位置減去之前記錄的相對(duì)點(diǎn)擊位置,就是新的窗口的位置了,這樣就實(shí)現(xiàn)了窗口的拖動(dòng)功能。
大小調(diào)整的思路則是判斷點(diǎn)擊位置是處于窗口的邊緣位置,如果是,改變鼠標(biāo)指針。如果位置處于左側(cè)或者上方,拖動(dòng)里改變寬/高,并改變窗口位置,如果在右側(cè)或者正文,拖動(dòng)時(shí)改變窗口的寬/高。

class CoverFrame extends JFrame {
    private Point point = new Point(0, 0); //用于保存點(diǎn)擊位置
    ...

    public CoverFrame() {
        ...
        addMouseListener(new MouseAdapter() { //監(jiān)聽鼠標(biāo)點(diǎn)擊
            public void mousePressed(MouseEvent event) {
                // record the point where you begin to drag
                point = event.getPoint();  //記錄點(diǎn)擊位置
                popupEvent(event);  //右鍵菜單
            }
            public void mouseReleased(MouseEvent event) {
                popupEvent(event);
            }

            private void popupEvent(MouseEvent event) {
                if (event.isPopupTrigger()) {
                    popupMenu.show(event.getComponent(), event.getX(),
                            event.getY()); //在右鍵位置顯示菜單
                }
            }

        } );

        addMouseMotionListener(new MouseMotionListener() {
            // 用來標(biāo)識(shí)點(diǎn)擊區(qū)域(上下左右)
            private boolean top = false;
            private boolean down = false;
            private boolean left = false;
            private boolean right = false;
            final private int GAP = 3;

            public void mouseMoved(MouseEvent event) {
                //窗體的寬高
                int width = getWidth();
                int height = getHeight();
                //點(diǎn)擊位置(相對(duì))
                int x = event.getX();
                int y = event.getY();

                top = false;
                down = false;
                left = false;
                right = false;
                if (Math.abs(y) <= GAP) {
                    top = true;
                } else if (Math.abs(y-height) <=GAP) {
                    down = true;
                }

                if (Math.abs(x) <= GAP) {
                    left = true;
                } else if (Math.abs(x-width) <=GAP) {
                    right = true;
                }
                //如果判斷在邊緣就改變鼠標(biāo)指針
                setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                if (top || down)
                    setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR));
                if (left || right)
                    setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
                if ((left && top) || (right && down))
                    setCursor(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR));
                if ((right && top) || (left && down))
                    setCursor(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR));
            }

            public void mouseDragged(MouseEvent event) {
                bounds = getBounds();
                if (!(top || down || left || right)) {
                    // 在中間拖動(dòng)窗口
                    Point absPoint = event.getLocationOnScreen();
                    // set the location of window relate to where you click
                    absPoint.translate(-(int)point.getX(),
                            -(int)point.getY());
                    setLocation(absPoint);
                } else {
                    //在四角縮放窗體
                    if (top) {
                        bounds.setLocation((int)bounds.getX(), (int)bounds.getY() + event.getY());
                        bounds.setSize((int)bounds.getWidth(), (int)bounds.getHeight() - event.getY());
                    }
                    if (down) {
                        bounds.setSize((int)bounds.getWidth(), event.getY());
                    }
                    if (left) {
                        bounds.setLocation((int)bounds.getX() + event.getX(), (int)bounds.getY());
                        bounds.setSize((int)bounds.getWidth() - event.getX(), (int)bounds.getHeight());
                    }
                    if (right) {
                        bounds.setSize(event.getX(),(int)bounds.getHeight());
                    }
                    validateBounds();
                    setBounds(bounds);
                }
            }
        } );
關(guān)閉與保存設(shè)置

關(guān)閉本來其實(shí)是沒啥說的,就算是沒有標(biāo)題欄,但是因?yàn)榘杨伾臀恢眯畔⒂涗浵聛?,還是有一些要注意的地方。

一般通過按鍵關(guān)閉窗口,會(huì)調(diào)用dispose函數(shù),但是這樣的話,并不會(huì)觸發(fā)windowClose的事件。要主動(dòng)發(fā)出這一事件才可以。

首先先設(shè)置關(guān)閉里的默認(rèn)動(dòng)作,并監(jiān)聽關(guān)閉事件,在保存設(shè)置后再退出。程序中設(shè)置的保存就很簡單的在文本文件中存了幾個(gè)數(shù)字,這里就不細(xì)說了。

public class Cover {
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                CoverFrame frame = new CoverFrame();
                frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);  //自己處理關(guān)閉
                frame.setVisible(true);
                frame.addWindowListener(new WindowAdapter(){  
                    @Override  
                    public void windowClosing(WindowEvent e) {  
                        super.windowClosing(e);  
                        frame.writeCfg();  // 保存設(shè)置
                        System.out.println("window is closed!");  
                        System.exit(0);
                    }  
                }); 
            }
        });
    }
}

但是問題來了,如果按Alt+F4關(guān)閉,那么設(shè)置會(huì)被保存,但直接dispose關(guān)閉程序,則不保存。這是因?yàn)闆]有觸發(fā)關(guān)閉的事件。主動(dòng)把一個(gè)關(guān)閉事件添加到事件隊(duì)列中,然后再dispose就解決了這一問題

class CoverFrame extends JFrame {
    ...
    private JPopupMenu popupMenu = new JPopupMenu();
    ...
    public CoverFrame() {
        ...
        // set up popup menus
        JMenuItem closeItem = new JMenuItem("Close");
        closeItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                // make sure close event is catched
                WindowEvent wev = new WindowEvent(that,
                        WindowEvent.WINDOW_CLOSING);
                Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev);  //主動(dòng)把一個(gè)關(guān)閉事件添加到事件隊(duì)列中
                dispose(); // close window
            }
        });
        popupMenu.add(closeItem);
        ...
    }
}
顏色修改

這個(gè)功能其實(shí)也不難,主要就利用了Java中自帶的選色窗口。不細(xì)說了,給代碼片段了。同樣要注意的是,同時(shí)設(shè)置CoverFrame的底色和ContentPane的底色。

class CoverFrame extends JFrame {
    ...
    private JPopupMenu popupMenu = new JPopupMenu();
    ...
    public CoverFrame() {
        ...
        JMenuItem pickItem = new JMenuItem("Pick Color");
        pickItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                Color newColor;
                setAlwaysOnTop(false);
                newColor = JColorChooser.showDialog(null, "pick your color",
                           color);
                setAlwaysOnTop(onTop);
                if(newColor != null) {
                    color = newColor;
                    setBackground(color);
                    getContentPane().setBackground(color);
                    repaint();
                }
            }
        });
        popupMenu.add(pickItem);
        ...
    }
}
總結(jié)

周五花了一個(gè)下午寫了這個(gè)程序,邊學(xué)邊做所以比較慢,又花了不少時(shí)間寫這些東西,不過越寫越感覺,只是一種心得的記錄而已,應(yīng)該沒有什么參考價(jià)值。

完整的代碼放在了
http://git.oschina.net/macuss...

兩百多行不太多,思路這里基本介紹了,功能吧基本能用。

本來想把參考的帖子都致敬一下的,不過有點(diǎn)麻煩,不好意思了。反正也是個(gè)人日記而已。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/67335.html

相關(guān)文章

  • 前端算法之彈幕設(shè)計(jì)

    摘要:本文愿從彈幕設(shè)計(jì)這個(gè)場景來描述算法在前端中的應(yīng)用,我們先來看下實(shí)現(xiàn)效果圖彈幕效果開場之前我們先來描述彈幕開發(fā)的難度,再集中精力描述算法設(shè)計(jì)的思路。軌道軌道這個(gè)角色很重要,它可以解決彈幕位置計(jì)算速度控制碰撞檢測(cè)問題。 大家都說前端寫頁面較多,幾乎用不到算法。本文愿從彈幕設(shè)計(jì)這個(gè)場景來描述算法在前端中的應(yīng)用,我們先來看下實(shí)現(xiàn)效果: showImg(https://segmentfault....

    Bryan 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<