簡單改寫一個Linux下最好用的截圖工具


點(diǎn)擊「閱讀原文」查看良許原創(chuàng)精品視頻。
點(diǎn)擊「閱讀原文」查看良許原創(chuàng)精品視頻。
因?yàn)槿粘inux辦公,經(jīng)常有截圖順帶簡單編輯的需求。
在Windows上這項(xiàng)工作基本一直是QQ微信代勞,但是在Linux上這兩個都比較拉胯,無奈之下找了幾種Linux下的截圖工具替代
試了幾個比較流行的,感覺下來最好用的算是flameshot,功能齊全運(yùn)行穩(wěn)定,圖標(biāo)也挺新潮,操作界面也很簡潔,基本毛病沒得挑。但唯一的缺點(diǎn)就是:「沒有全局熱鍵。」
好在flameshot是個開源軟件,下下來源碼瞅了一眼,是我熟悉的Qt寫的,感覺全局熱鍵這部分可以自己整合一下。
源碼中對全局熱鍵的實(shí)現(xiàn)只放開了windows,而且從源碼來看好像也只預(yù)留了接口沒實(shí)現(xiàn)功能。簡單研究了一下,通過一個名為qxtglobalshortcut5的Qt全局熱鍵第三方庫可以輕松實(shí)現(xiàn)
使用
先把現(xiàn)成的工具放出來吧,伸手黨福利:https://kdocs.cn/l/sgGCbHx3wSaM [金山文檔] flameshot
復(fù)制鏈接到瀏覽器直接下載,啟動后任務(wù)欄會有圖標(biāo),點(diǎn)擊 Take Screenshot即可截圖
點(diǎn)擊一次截圖后,全局熱鍵才可以使用。“Ctrl + F5” 即可觸發(fā)截圖(ubuntu源內(nèi)自帶的qt5.5編譯會有這個問題,qt5.7編譯出的程序直接啟動后全局熱鍵就可以用)。 自己編譯的話是有翻譯的,這里單程序沒有翻譯文件,所以都是英文,不過不影響使用。 效果如圖:具體的使用快捷鍵和功能去其他地方查一下吧,我就不搬運(yùn)了,都是很基本的截圖編輯操作,好用得很: 
建議在設(shè)置里開機(jī)自啟,或者加 nohup ...... &啟動,不占用終端。這個程序我是用的 ubuntu16.04源內(nèi)自帶的庫編譯的,所以僅僅適用于ubuntu 16.04。換到其他Linux系統(tǒng)不一定能用。其他Linux平臺會因?yàn)椴蛔詭t或者自帶qt庫版本不一樣導(dǎo)致不能用的問題,最好的辦法是自行下載編譯,方法如下:
編譯(Ubuntu 16.04環(huán)境)
環(huán)境準(zhǔn)備
Ubuntu16.04自帶了一些Qt5.5.1的核心庫,但是要編譯的話還需要qmake,lrelease等工具,還有x11extras svg等qt插件支持,需要安裝:
sudo?apt-get?install?qt5-default
sudo?apt-get?install?qttools5-dev-tools
sudo?apt-get?install?libqt5svg5-dev
sudo?apt-get?install?libqt5x11extras5-dev
sudo?apt-get?install?qtbase5-private-dev
都直接從源里下,這樣能保證都是配套同一個版本的。
獲取flameshot源碼:
地址:https://github.com/lupoDharkael/flameshot.git
git?clone?https://github.com/lupoDharkael/flameshot.git
編譯源碼
cd?flameshot
mkdir?build?
cd?build?
qmake?../?
#?報錯沒有qmake的話,要裝上面的庫
make?-j`nproc`
sudo?ln?-sf?`pwd`/flameshot?/usr/bin/flameshot
編譯完成后,會生成一個可執(zhí)行文件flameshot,可以直接放一個軟連接到/usr/bin下面
增加全局熱鍵功能
一、獲取qxtglobalshortcut5項(xiàng)目到此項(xiàng)目中
#?離開剛才的編譯目錄
cd?../?
#?pwd:?~/flameshot
git?clone?https://github.com/ddqd/qxtglobalshortcut5.git
flameshot項(xiàng)目和qxtglobalshortcut5這個項(xiàng)目都是qt的pro管理的,整合起來非常方便
在獲取到qxtglobalshortcut5項(xiàng)目后,flameshot項(xiàng)目下就有這個玩意兒:
qxtglobalshortcut5的實(shí)現(xiàn)已經(jīng)相當(dāng)完善了,引入后一行都不需要改,只需要改寫flameshot項(xiàng)目
在flameshot.pro文件中添加一行:include(qxtglobalshortcut5/qxt.pri)
QT??+=?core?gui?widgets?network?svg
unix:!macx?{
????QT??+=?dbus
}
CONFIG?+=?c++11?link_pkgconfig
include(qxtglobalshortcut5/qxt.pri)???#?這一行是新加的
#CONFIG?+=?packaging???#?Enables?"make?install"?for?packaging?paths
TARGET?=?flameshot
TEMPLATE?=?app
二、源碼里注冊全局熱鍵
打開src/core/controller.cpp這個文件,找到Controller的構(gòu)造函數(shù),在這里注冊全局熱鍵:
Controller::Controller()?:?m_captureWindow(nullptr)?{
????qApp->setQuitOnLastWindowClosed(false);
????//?init?tray?icon
#if?defined(Q_OS_LINUX)?||?defined(Q_OS_UNIX)
????if?(!ConfigHandler().disabledTrayIconValue())?{
????????enableTrayIcon();
????????}
????????/**?注冊全局熱鍵!?*/
????????QxtGlobalShortcut*?shortcut1?=?new?QxtGlobalShortcut(QKeySequence("Ctrl+F5"),?this);?
????????/**?全局熱鍵觸發(fā)的函數(shù)!?*/
????????connect(shortcut1,?SIGNAL(activated()),?this,?SLOT(shortcutActiveCapture()));?
#elif?defined(Q_OS_WIN)
????enableTrayIcon();
????GlobalShortcutFilter?*nativeFilter?=?new?GlobalShortcutFilter(this);
????qApp->installNativeEventFilter(nativeFilter);
????connect(nativeFilter,?&GlobalShortcutFilter::printPressed,
????????????this,?[this](){
????????this->requestCapture(CaptureRequest(CaptureRequest::GRAPHICAL_MODE));
????});?
#endif
????QString?StyleSheet?=?CaptureButton::globalStyleSheet();
????qApp->setStyleSheet(StyleSheet);
}
這里除了注釋的兩行是我加的,其他都是原來的代碼,這個庫支持字符串的形式注冊全局熱鍵,Ctrl+F5可以換成你自己喜歡的。
因?yàn)闆]有在Window上測試過們這里只加給了Q_OS_LINUX環(huán)境,理論上這個全局熱鍵的庫各平臺都是通用的,不過我只需要Linux。
三、全局熱鍵的處理函數(shù)
上面給shortchut1注冊了一個槽函數(shù)shortcutActiveCapture,這個函數(shù)還沒有實(shí)現(xiàn),這個函數(shù)的功能很簡單,只需要調(diào)用截圖函數(shù)就行,可以查一下我們點(diǎn)擊截圖觸發(fā)的是哪一個函數(shù),我們也調(diào)用同一個函數(shù)即可:
src/core/controller.h文件,在頭文件里,添加函數(shù)聲明:
private?slots:
????void?startFullscreenCapture(const?uint?id?=?0);
????void?startVisualCapture(const?uint?id?=?0,
?????????????????????????????const?QString?&forcedSavePath?=?QString());
????void?startScreenGrab(const?uint?id?=?0,?const?int?screenNumber?=?-1);
????void?handleCaptureTaken(uint?id,?QPixmap?p);
????void?handleCaptureFailed(uint?id);
????void?shortcutActiveCapture();?//這一句是追加的
src/core/controller.cpp文件,在實(shí)現(xiàn)文件里,添加函數(shù)實(shí)現(xiàn):
void?Controller::shortcutActiveCapture()
{
????this->startVisualCapture(0,QString());
}
「四、重新編譯運(yùn)行」
進(jìn)入到剛才的編譯目錄,重新執(zhí)行qmake,make編譯就可以了。
cd?build?
qmake?../
make?
編譯好后可以試一下,生成的可執(zhí)行程序運(yùn)行后可以通過全局熱鍵Ctrl+F5進(jìn)行截屏編輯操作。
這個改動非常簡單,通篇使用的是Ubuntu源內(nèi)自帶的工具和庫。即使沒怎么接觸過qt的人,按照上面的套路也可以把這個工具輕松整出來。
如果是Qt老炮,可以通過本地編譯出來或者本地安裝的其他版本的qt編譯這個程序,目前嘗試qt5.5.1全局熱鍵還是有點(diǎn)問題的,上面也提到了。我本地用的qt5.7沒有這個問題。
存在問題:失去焦點(diǎn)就消失的窗體
理論上可以點(diǎn)擊截圖的地方,完全用不到全局熱鍵,只有一種場景對全局熱鍵截圖這個功能有剛需:失去焦點(diǎn)窗體就消失的情況。比如,你在chorme瀏覽器的某個標(biāo)簽頁上右鍵彈出一個對話框,你想截圖這個對話框里的內(nèi)容,但是一旦你鼠標(biāo)去點(diǎn)擊截圖的按鈕,這個對話框就會因?yàn)槭ソ裹c(diǎn)而消失。這個時候就需要截圖全局熱鍵的功能來實(shí)現(xiàn):
或者對一些鼠標(biāo)懸停才會顯示的內(nèi)容tooltips的截圖也是這樣:
但遺憾的是,在Linux平臺上,這個全局快捷鍵截圖仍然不能非常完美的解決所有“失焦即焚”窗體的問題
比如說你隨便打開一個窗口,鼠標(biāo)挪到左上角隨便點(diǎn)一個選項(xiàng)卡(文件、修改、視圖等等的),當(dāng)他出現(xiàn)菜單時,你想截圖這個菜單的內(nèi)容,你就會發(fā)現(xiàn)全局熱鍵不好使了:
當(dāng)這個紅框窗體拿到焦點(diǎn)的時候,全局熱鍵就不好使了,為了讓全局熱鍵生效讓他失去焦點(diǎn),這個窗體又會消失。進(jìn)入到一種無法截圖的尷尬境地。(我這張是對著虛擬機(jī)截出來的)
但這個問題并不是qxtglobalshortcut5實(shí)現(xiàn)的問題,而是X11本身的限制,一個直觀的證據(jù)就是:在這種情況下,你鍵盤上的PrintScreen按鍵也會失效。
為了這個問題大概看了下qxtglobalshortcut5的Linux部分的實(shí)現(xiàn),確實(shí)已經(jīng)是x11提供的XGrabKey所能提供功能的極限了,如果硬要讓自己全局熱鍵的優(yōu)先級高于窗口管理器,可能得寫驅(qū)動級別的程序來搞。
存在問題2:輸入文字不支持輸入法
文字只能輸入英文,這個也比較坑,目前還在想辦法,目測可以用加載ibus/fcitx輸入法插件的方式解決,后期解決后回來更新,有了解的大佬歡迎不吝賜教。
推薦閱讀:
5T技術(shù)資源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,單片機(jī),樹莓派,等等。在公眾號內(nèi)回復(fù)「1024」,即可免費(fèi)獲取!!
