当前位置: 首页 > 工具软件 > Qtile > 使用案例 >

linux窗口管理软件,Linux窗口管理器——Qtile之初体验

王俊楚
2023-12-01

Tiling window manager——平铺式窗口管理器,不同于浮动式那样以层的形式管理窗口,平铺式将所有窗口平铺开来,窗口之间无缝对接,这有助于同时查看多个窗口的内容,对于程序员来说这尤其有用。

平铺式窗口管理器有很多,比较有名的像awesome,i3等等,不过awesome是以lua语言写的,我没用过,对此不做介绍。而qtile是以纯Python写的,作为一个Python迷(虽然海是菜鸟中的菜鸟),我自然选择qtile。

Qtile的图形对象(object graph)共七个部分:layouts、windows、screen、groups、bars、widgets还有一个root。

layouts:布局,以什么方式来分布窗口,包括Max(单窗口占据整个屏幕)、Tiling(按比例分配窗口)、Floationg(浮动窗口)、MonadTall(模拟XMonad的平铺式窗口)、Slice、Stack(将屏幕分成多个栈),TreeTab、Zoomy

groups:相当于其他桌面环境的工作区。

screens:物理屏幕

bar:栏,可以理解为任务栏

widget:小工具,组件,包括很多,像是时间,天气,邮件查看,任务列表,groupbox等等。。。

安装qtile的方法可以参考官网,不过我当时照着官网编译的时候提示错误,是一个ImportError,好像是说缺少某个模块,不过这个模块我没有找到。。。后来在google了一番后,找到如下的解决方法:pip install cffi

pip install xcffib

git clone -b xcb https://github.com/flacjacket/cairocffi.git

cd cairocffi && sudo python setup.py install

git clone git://github.com/qtile/qtile.git

cd qtile

sudo python setup.py install

貌似是作者把几个模块编译到了一起。。。

关于配置文件的写法官网上提供了很多,既有默认配置,也有其他用户写的配置,可以借鉴后使用。之后我会给出我的配置,不过就是并不好。

详细的内容可以看官方文档,不过官方文档并不全面,很多配置都未提到。尤其是关于windows(窗口对象)方面的,除了官方默认配置外,其他用户的配置都用到了windows方面的内容。我谷歌、度娘了半天,一无所获(也可能是我查的方式不对)。看来可能要直接看源代码了。。。

刚才传了一下,好像不怎么好上传,现直接贴出配置文件:#!/usr/bin/env python

#-*-coding:utf-8-*-

import os

from libqtile import layout,widget,bar,manager,hook

from libqtile.widget import base

from libqtile.manager import Screen,Drag

from libqtile.command import lazy

try:

from libqtile.manager import Key,Group

except ImportError:

from libqtile.config import Key,Group

sup='mod4'

alt='mod1'

#键位映射

keys=[

#Layout

Key([sup],'Down',lazy.layout.down()),

Key([sup],'Up',lazy.layout.up()),

Key([alt],'Tab',lazy.layout.next()),

Key([alt,'shift'],'Tab',lazy.layout.previous()),

Key([sup],'space',lazy.nextlayout()),

Key([sup],'k',lazy.layout.increase_ratio()),

Key([sup],'j',lazy.layout.decrease_ratio()),

Key([sup],'l',lazy.layout.increase_nmaster()),

Key([sup],'h',lazy.layout.decrease_nmaster()),

#Window

Key([alt],'F4',lazy.window.kill()),

Key([alt],'F10',lazy.window.toggle_maximize()),

#Group

Key([sup],'Left',lazy.group.prevgroup()),

Key([sup],'Right',lazy.group.nextgroup()),

#Application launchers

Key([sup],'Return',lazy.spawn('sakura')),

Key([sup],'f',lazy.spawn('firefox')),

Key([sup],'m',lazy.spawn('vlc')),

Key([sup],'v',lazy.spawn('virtualbox')),

Key([sup],'t',lazy.spawn('Thunar')),

Key([sup],'q',lazy.spawn('QQ')),

Key([sup],'z',lazy.spawn('zim')),

#Audio

Key([sup],'F8',lazy.spawn('amixer --quiet set Master mute')),

Key([sup],'F9',lazy.spawn('amixer --quiet set Master unmute')),

Key([alt],'minus',lazy.spawn('amixer --quiet set Master 2dB-')),

Key([alt,'shift'],'equal',lazy.spawn('amixer --quiet set Master 2dB+')),

#restart qtile

Key([sup],'r',lazy.restart()),

#shutdown

Key([sup,'shift'],'q',lazy.spawn('shutdown -h now')),

#interact with prompts:

Key([sup],'s',lazy.spawncmd()),

]

mouse=[

Drag([sup],"Button1",lazy.window.set_position_floating(),

start=lazy.window.get_position()),

Drag([sup],"Button3",lazy.window.set_size_floating(),

start=lazy.window.get_size()),

]

#建立groups

group_names=[

("code1",{'layout':'tile'}),

("code2",{"layout":'tile'}),

("web",{"layout":"max"}),

("vbox",{"layout":"max"}),

('music',{'layout':'max'}),

('doc',{'layout':'max'}),

('chat',{'layout':'max'})

]

groups=[Group(name,**kwargs) for name,kwargs in group_names]

for i , (name,kwargs) in enumerate(group_names,1):

keys.append(Key([sup],str(i),lazy.group[name].toscreen()))

keys.append(Key([sup,'shift'],str(i),lazy.window.togroup(name)))

#建立layouts

layouts=[

layout.Tile(border_focus='#196ff2',border_width=1),

layout.Max()

]

font='WenQuanYi Micro Hei'

fontsize=16

foreground='#FFFFFF'

background='#000000'

def humanize_bytes(value):

suff=['B','K','M','G','T']

while value > 1024. and len(suff)>1:

value/=1024.

suff.pop(0)

return "% 3s%s" %('%.3s'%value,suff[0])

#本来这个是用来显示CPU、Mem、Net的情况,后来不知为何无法显示

class Metrics(base._TextBox):

defaults=[

('font','Arial','Metrics font'),

('fontsize',None,'Metircs pixel size'),

('pading',None,'Metrics padding'),

('background','00000','background color'),

('foreground','ffffff','foreground color')

]

def __init__(self,**kwargs):

base._TextBox.__init__(self,**kwargs)

self.cpu_usage,self.cpu_total=self.get_cpu_stat()

self.interfaces={}

self.idle_ifaces={}

def _configure(self,qtile,bar):

base._TextBox._configure(self,qtile,bar)

self.timeout_add(0,self._update)

def get_cpu_stat(self):

stat=[int(i) for i in open('/proc/stat').readline().split()[1:]]

return sum(stat[:3]),sum(stat)

def get_cpu_usage(self):

new_cpu_usage,new_cput_total=self.get_cpu_stat()

cput_usage=new_cpu_usage-self.cpu_usage

cpu_total=new_cpu_total-self.cpu_total

self.cpu_usage=new_cpu_usage

self.cpu_tptal=new_cpu_total

return 'Cpu: %d%%' % (float(cpu_usage)/float(cpu_total)*100.)

def get_mem_usage(self):

info={}

for line in open('/proc/meminfo'):

key,val=line.split(':')

info[key]=int(val.spilt()[0])

mem=info['MemTotal']

mem-=info['MemFree']

mem-=info['Buffers']

mem-=info['Cached']

return 'Mem: %d%%' % (float(mem)/float(info['MemTotal'])*100)

def get_net_usage(self):

interfaces=[]

basedir='/sys/class/net'

for iface in os.listdir(basedir):

j=os.path.join

ifacedir=j(basedir,iface)

statdir=j(ifacedir,'statistics')

idle=iface in self.idle_ifaces

try:

if int(open(j(ifacedir, 'carrier')).read()):

rx = int(open(j(statdir, 'rx_bytes')).read())

tx = int(open(j(statdir, 'tx_bytes')).read())

if iface not in self.interfaces:

self.interfaces[iface] = (rx, tx)

old_rx, old_tx = self.interfaces[iface]

self.interfaces[iface] = (rx, tx)

rx = rx - old_rx

tx = tx - old_tx

if rx or tx:

idle = False

self.idle_ifaces[iface] = 0

rx = humanize_bytes(rx)

tx = humanize_bytes(tx)

interfaces.append('%s: %s / %s' % (iface, rx, tx))

except:

pass

if idle:

interfaces.append('%s: %-11s' % (iface, ("%ds idle" % self.idle_ifaces[iface]))

)

self.idle_ifaces[iface] += 1

if self.idle_ifaces[iface] > 30:

del self.idle_ifaces[iface]

return " | ".join(interfaces)

def _update(self):

self.update()

self.timeout_add(1, self.update)

return False

def update(self):

stat = [self.get_cpu_usage(), self.get_mem_usage()]

net = self.get_net_usage()

if net:

stat.append(net)

self.text = " | ".join(stat)

self.bar.draw()

return True

screens=[

Screen(top=bar.Bar([

widget.TextBox(text='◤ ',fontsize=40,foreground='#323335',padding=0),

widget.GroupBox(font=font,fontsize=fontsize,active=foreground,inactive="#808080",borderwidth=3),

widget.Prompt(font=font,fontsize=fontsize),

widget.CurrentLayout(font=font,foreground=foreground,fontsize=fontsize),

widget.Sep(foreground=background,linewidth=3),

widget.WindowName(font=font,fontsize=fontsize,foreground=foreground),

widget.Notify(font=font,fontsize=fontsize),

Metrics(font=font,fontsize=fontsize,foreground=foreground),

widget.Volume(foreground="#70ff70"),

widget.BatteryIcon(),

widget.Systray(icon_size=18),

widget.Clock(font=font,fontsize=fontsize,foreground=foreground,fmt='%Y-%m-%d %a %H:%M'),

],30))

]

@hook.subscribe.client_new

def dialogs(window):

if(window.window.get_wm_type() == 'dialog'

or window.window.get_wm_transient_for()):

window.floating = True

 类似资料: