2020年8月28日 星期五

python tkinter 重要語法記錄

 

 

 

 

重要語法:

 

 

 

##=========================================================

Combobox的用法:

  

   

def printWarmOrMove(self):

    #if en_opt_WarmOrMove.get() == '警告':

    if self.get() == '警告':

        showinfo("Select", '只作警告')

    else:

        showinfo("Select", '將超過時間的信件移至目的信箱!')

 

 

def  mycombo(root,brow,myLabel,Entrywidth,opt_value):

 

#    Label_width=17

#    Label_Column=2

#    Entry_Column=3

   

    Label(root,text=myLabel,width=Label_width).grid(row=brow,column=Label_Column, sticky=E,columnspan=1)

 

    sv_opt_WarmOrMove = StringVar()                                                         è 建立 StringVar()

    en_opt_WarmOrMove = ttk.Combobox(root, width=Entrywidth, textvariable=sv_opt_WarmOrMove)  è 建主 combobox.

    en_opt_WarmOrMove['values'] = opt_value                                        è combobox item 加入 combobox[‘values’].

 

    en_opt_WarmOrMove.grid(row=brow,column=Entry_Column,sticky=W)      # 设置其在界面中出现的位置 column代表列 row 代表行

    en_opt_WarmOrMove.current(0)                                                          è 預設停在第一個item .

   

    #en_opt_WarmOrMove.bind("<<ComboboxSelected>>",printWarmOrMove) 

   

    en_opt_WarmOrMove.bind("<<ComboboxSelected>>",lambda e:printWarmOrMove(en_opt_WarmOrMove)) è 只傳入元件自己.

                                                                                                                  後來發現, 其實也可以 ,lambda e:printWarmOrMove(e) 再由 函數內自己解析 元件.

   

    return en_opt_WarmOrMove

 

 

##=========================================================

Listbox 如何用 for 取出所有item

 

    for item in listbox.get(0,END):

        mstart = item.index('>')+2

        mend   = item.index('.',mstart)

        #print(mstart,mend,item[mstart:mend])

        mtime = int(item[mstart:mend])

        if mtime > en_moveTimeInterval_value:

 

 

##==========================================================

如何建立網路磁碟機

 

def getmail(path,mailbox,driver):

    comNet = win32com.client.Dispatch("WScript.Network")

    NetDriver = driver                                                                                      è 本地端的磁碟機代號

    data = {}

    remote = path + '\\' + mailbox

    data['remote'] = remote

    data['local'] = NetDriver

    data['password'] = 'password'

    data['user'] = 'user'

    Lst_Folder = []

    

    #連線網路磁碟機

    #comNet.MapNetworkDrive(data['local'], data['remote'], False, data['user'], data['password']);

   

    try:

        comNet.MapNetworkDrive(data['local'], data['remote'], False, data['user'], data['password']);

    except:

        pass

        #print("win32net.NetUseAdd(None, 1, data) Fail")

 

 

          Lst_Folder_org = os.listdir(NetDriver)

 

##=========================================================

Listbox 沒有 scroll , 如要則要自己加, 同時要自己定位

##=========================================================

 

    brow = brow + 1

   

    scrolly=Scrollbar(root,width=20,orient=VERTICAL)                                    è 產生垂直的 scroll .

    scrolly.grid(row=brow,column=5,padx=(10,100),sticky=N+S+E)               è 定位, 注意, 要配合 padx(10,100), sticky 才能與listbox配好位罝.

   

    mailbody_listbox=Listbox(root,width=mailbody_width,height=mailbody_height,font=small_font)

    

    mailbody_listbox.grid(row=brow,column=2, sticky=W,padx=(30,0),columnspan=5)

      

    mailbody_listbox['yscrollcommand']=scrolly.set                                        è 告知 listbox yscrollcommand 要用 scroll.set

    scrolly['command'] = mailbody_listbox.yview                                                è 告知 scrolly command 要用 listbox.yview

 

 

##=========

如何在 bind 傳入 e 以及自訂義傳數. 注意這種作法會傳送機動的值, 而非傳送定義時的值.

##=========

## bind lambda ,記得要傳入 e è

就是傳入 event object , 提供給 mailbox_onselect(evt,myscreen) 接收.

 

box_mailbox1.bind('<<ListboxSelect>>', lambda e: mc.mailbox_onselect(e,myscreen))

 

 

## mailbox_onselect接收後, 透過 以下語法, 就可取出元件.

 

def mailbox_onselect(evt,myscreen):

    # Note here that Tkinter passes an event object to onselect()

    w = evt.widget                                 è 取出onselect的元件

    index = int(w.curselection()[0])                  è 取出 目前選取的是第幾個item

    value = w.get(index)                                      è 取出該item 內容. 應該為字串

    print('You selected item %d: "%s"' % (index, value))

   

    ## get file from value

    startpos = value.index('.')+1

    endpos   = value.index(' =>')

    email_filename = value[startpos:endpos]  è 取出 msg 的檔名.  è 等同於 substring(start,endpos)

 

          ## 如何取出元件名稱, w Listbox元件, 不是元件名稱, 取出元件名稱要用:

       if str(w) == '.!listbox':

 

 

##=============

 

路徑名合併重點:

 

file = r"\\123.123.123.123\e$\aa\bb\cc”+ "\\" +mailbox + "\\" + email_filename

 

重點1:

r” "\\123.123.123.123\e$\aa\bb\cc”

r會保留字串內的 \ , 但注意最後不可為 \” , 否則仍會出錯. 所以要去掉最後的 \.

“\\” 中間的 \ 要改用 \\,

 

 

##==============================================

Listbox內某個item 的設定, 要用 listbox.itemconfig(index,{設定,設定})

##==============================================

mailbody_listbox.insert(END, tt)   è 由後面END往後再加入, 所以表示也可以間加入. 如要刪除則 .delete(0,END)

mailbody_listbox.itemconfig(item_cnt, {'fg':color,'bg':'yellow'})

 

 

##===========

部份widget 沒有text , 是要用 以下指令指定內容, 例如Entry:

aa.delete(0,end)

aa.insert(0, def_text_val)

 

Label 如沒掛 StringVar, 可用

Label[‘text’]指定字串內容.

 

##==========

 

 

##===========

aa = Button(..).grid(…) 會失效, 要分開寫

 

aa = Button(..)

aa.grid(…) aa才會有效

 

##===========

 

aa = Button(….command=somefunc) ç 不會傳送 event 參數, 如要自代參數要用

 

aa = Button(….command=lambda: x:somefunc(x,para1,para2,para3) ç lambda 那個 x 就是 event object.

 

如要傳event 則要分開指定

Aa = Button()

aa.bind(‘<Button-1>’,somefunc)

mouse 的三個按鍵:

‘<Button-1>’

‘<Button-2>’

‘<Button-3>’

 

 

##======================================================================

tkinter 如要作定時循環作業, 無法用正常 thread進行定時作業, 而要用 root.after(秒數量1000, somefunc) 的方式重覆call 自己.

 

def reshowmailbox(…):

 

 

  if CheckVar1.get() == 1 :

        root.after(int(en_TimeInterval.get())*1000, lambda: reshowmailbox(….)

        print('reshowmailbox root after ')

 

##===========

由於 Checkbutton 沒有 get 可以取出值, 故要去存取他的 BooleanVar,

為方便存取 root 上的各元件, 故最好要自訂一個dict 去記錄screen 上有那些元作, 這樣才能將 screen 拆成不同部份單獨完成.

像我這個例子就是用myscreen[‘mailbox_listbox’] = mailbox_listbox

 

 

##========================

 

Checkbox 無法取得他是否己勾選, 要去檢查內含在它內部的 IntVar().

CheckVar1 = IntVar()

myscreen['CheckVar1'] = CheckVar1

 

CheckVar1.get() ç 這樣取出,

 

##==================================

##============================================

 

 

  comNet = win32com.client.Dispatch("WScript.Network")

    NetDriver = driver

    data = {}

    #remote = r'\\192.168.x.x\d$\aaa\bbbs\ccc.com\usermailfolder'

    remote = path + '\\' + mailbox

    data['remote'] = remote

    data['local'] = NetDriver

    data['password'] = 'password'

    data['user'] = 'user'

    Lst_Folder = []

    

    #連線網路磁碟機

    #comNet.MapNetworkDrive(data['local'], data['remote'], False, data['user'], data['password']);

    

    try:

        comNet.MapNetworkDrive(data['local'], data['remote'], False, data['user'], data['password']);

 

 

##==============================

listbox 的長度要用 size()

 

user_listbox=Listbox(root,…)

user_listbox.grid(row=brow..)

 

   for item in items:

        f_item = "{0:30}".format(item)

        user_listbox.insert(END, f_item)

 

 

    if user_listbox.size() > 1:

        user_listbox.itemconfig(0, {'fg':'red'})

 

##==============================

## 剛發現好用的 exec() 類似 clipper macro

   Clipper macro :

##==============================

     cMacro := "DTOC(DATE())"

     ? &cMacro

     ? &(INDEXKEY(0))

##==============================

 

 

for i in range(5):

    object = 'test' + str(i) + '=' + str(i*2)

    print(object)

    exec(object)   ## è 結果真的產生了 test1/test2… test5的變數.

 

##==============================

 

 

2020年5月25日 星期一

無意間發現 system explorer 可以暫停 "XX保護服務" 佔用 CPU.


你是否常遇到 "XX保護服務" 佔用大量cpu 而讓你的電腦卡卡的. 




查詢 google 大神,試著手動去停止該服務, 但仍無效, 讓你的電腦常常卡頓卡頓. 

我在無意間發現 system explorer 可以將這個服務(sppsvc.exe)作暫停. 注意, 是暫停, 而不是停止, 一旦暫停, 它就不佔用CPU , 發現效果還不錯.  但我有試著手動開啟系統服務劃面卻無法讓這個服務暫停. 不知道是不是一個bug 或漏洞, 將來不知道是不是會補起來, 不知道, 不過, 目前是可以用的.





由於網路上有人說這個服務會跟有些軟體使用上有關, 也就是有些軟體在運作時, 這個服務開啟才能正常運作. 但我測試時好像還好, 沒有遇到這樣的情況. 

如要避免, 則建議開機時, 讓這個服務運作一陣子後, 開啟你要用的程式後, 再去作暫時, 不要開機後就急著去暫時, 讓系統中該檢查的動作作完後, 再來暫停, 這樣應該就問題會比較少. 

什麼, 你不知道什麼是 System Explorer , 喔, 還建議你 google 一下, 或者上X榮X利味找找, 應該可以找到.






2020年1月21日 星期二

好用的通用型資料庫工具 dbeaver


經朋友介紹, 得知這個工具,
下載網址為:https://dbeaver.io/download/
區分為 免費的 community 版本與要錢的 Enterprise 版本.
我是測免費版本, 功能就己很多,




支援的資料庫還滿齊全的:



下載時又區分為 zip 版本(應為免安裝版本)install 版本.


測試時有發現一些重點:

重點1:
由於該工具是用 java 寫成, 所以要注意與 java 配合, 依網頁說明, 下載 zip 版本, 照理說 java 有安裝好, 應該就可以執行. 但我測試發現, 我在兩台都有裝 java 的電腦測試, 發生一台可以順利使用, 另一台則一直出現 error 13, 連上網查, 好像都是說 java 有問題,

結果我就在無法跑的那台下載 install 版本, 結果就可以執行, 所以看來可能用 install 版本會比較穩定.


剛看到, 原來 install 版本有附 jre :

"Included JRE will be accessible only for DBeaver."

所以應該不用裝 java , 就直接裝 install 版本, 這點可能要找時間測一下. 


重點2:
測試時以 sql server 作為測試資料庫, 發現正常情況是可以連, 但遇到 有install name 的資料庫就連不起來. 例如 127.0.0.1\SQLExpress  , 目前還找不出解決, 還是其實是無解.

而其它資料庫測試則晚點再逐步來測試.

重點3:
發現在裝 java 時, 發現有出現版權警告, 似乎有看到 Oracle 己取消 java 完全免費的作法, 好像有看到除了測試及個人用外, 好像其它情況是要付費的.
如果是上面這種情況, 那就表示, 如果要商用, 則雖然 dbeaver 是免費, 但你的 java 環境可能是要付費用. 這點可能要注意.




2020年1月15日 星期三

好用的 Chrome 插件 IE Tab , stream recorder







20200121:
感謝朋友介紹, 發現 另一個好用的 擴充功能 stream recorder, 可以錄下 Stream 的視訊. 剛測, 好像可以用, 可以方便的錄下 youtube 模式的Stream 視訊. good


20200121:
發現IE Tab 好像不支援 flash, 這個可能要注意一下. 其它部份, 現在好像都正常.
比較值得提的, 用 IE Tab 開啟的網頁, 好像都是 InPrivate nPrivate 模式, 各自的Session 是獨立, 不會互相干擾, 這個在某些網頁功能上來說其實是好事. 至少我寫的程式就會比較安定, 不會開啟兩個就互相干擾. good



剛測:
發現新版用 chromium 為核心的 edge , 也可以套用 chrome 的擴充功能, 只是不能直接在 edge 的 app store 去找, 而是先在 chrome 找到後, copy 網址到 edge , 這時就可以把擴充功能加到 edge 上了.

---------------------------------------------------------------------------------------------------------


由於舊網頁的關係, 須要使用到舊版IE, 又不想離開常用的chrome, 這時就可以在chrome 使用 IE Tab ab 的這個擴充套件.








加入後 chrome 的位置列右邊會出現 ie tab 的圖示, 按了之後, 就會在原來的 位置列下方多出一個IE的位置列.



在IE Tab IE Tab 列內輸入網址, 就能以IE 模式瀏覽該網頁.

如有進階需求, 則可以按IE Tab Tab 右邊的工具icon 進入設定, 目前己知重要設定有:
1. 可以設定自動啟用 IE Tab 的網址, 打入對應的網址, 就會自動啟動 IE Tab.
2. 設定 IE Tab 所要模擬的 IE 版本.

以上是我目前有用到的 進階功能.

提供給大家參考.

2020年1月7日 星期二

利用python 寫一支監控mdaemon domain pop 的程式.





20200121:
1. 己寫出大致scan功能. 但如果卡住後續處理方式還在觀察當中.
觀察重點:
1.卡多久才算卡住, 因為我有發現10幾分的信, 最後仍會消化掉.
2. 如果真的發現卡住, 那如何處理,
    a. a. 原預計是把同一個卡住時間點(以分為單位), 移至另一個資料夾, 但
            有發現手動移動信件, 其實仍卡住.
    b. 是否除了移信外, 仍要想辦法至目的端mdaemon 重新啟用 mdaemon server 才行.

有看到網路提到重啟遠端服務的作法:

step1 : 先登入對方主機:
net use \\遠端主機IP  "password"  /user:"admin"

第一種作法:
   net start [servicesname]
   建議中間要 delay 10 秒
   net stop [servicesn

第二種作法:
   停止服務:
   sc \\遠端主機IP stop services_name

   建議中間要 delay

   啟動服務:
   sc \\遠端主機IP start services_name


以上兩種作法可能要測一下.

    以上兩點還在觀察當中.
-------------------------------------------------------



原理:

mdaemon 的信件存放架構為:

domain 層: 一個domain 佔用一個資料夾, 所有使用者再掛到該資料夾下.
使用者信箱層: 每個信箱佔用一個在domain 層下的一個資料夾, 所有信件均會收到這個資料夾內.

對方要作domain pop 的mdaemon server  則會定時來這個使用者信箱取出信件, 轉送至對方的email 主機內.

domain pop 主機取走所有信件後, 會再依收件者名字, 轉發至該主機上的信箱上.

------------------------------------------------------------------
利用這個特性:

寫一支定時批次程式, 去監控這個domain pop 信箱上的信件的 age , 如果過老, 例如超過 15分, 則應該就表示domain pop 卡住了.

因為預設domain pop 的時間為 5分鐘作一次, 所以如果沒有卡住, 信件的 age 應不會超過 5分鐘

chromecast 開箱試用 與miracast 比較.



參考以下網址內容, 一直納悶, 如何可以順利安裝,

https://support.google.com/chromecast/answer/2998456?co=GENIE.Platform%3DAndroid&hl=zh-Hant


不過, 昨天晚上實際安裝, 卻出奇的順利:

1. chromecast 接到電視的HTMI 2 接口. 另用usb線 接電視的usb 電源.
2. 手機下載 chrome home , 登入 google 帳號後, 依提顯, 開啟 wifi 以及 位置 開關.
3. 一下子app 就抓到 chromecast 的 id.
4. 直接點選給予 '客廳' 代號, 就連起來.
5. 接著就可以順利播放 youtube 及 其它影片.


pro & corn

1. youtube + MV 播放片:影片效果超好.
2. 相片效果則一般.
3. 支援的影片有格式限制. 而且目前好像mkv 無法上字幕.
4. 支援的app 有限, 跟 miracast不限app 不同.

如何知道我的裝置是否支援Wi-Fi Miracast


miracast :
1. ovo 要下載miracastapp , app , 開啟app, 等待配對.
2. 手機在設定--> 裝置內找到 miracast--> 啟用再與 ovo 配對.
3. 上述兩個設備要連上同一台wifi.
4. 配對後, 手機劃面就整個出現在電視上.
5. 手機的劃面轉向會影響到電視的播放, 這點不是很方便.
6. 電影播放時, 無法佔滿整個電視劃面, 效果沒有chromecast一樣.



2019年12月27日 星期五

x32舊版程式如何移至 x64

x32舊版程式如何移至 x64

1. 原odbc  連接要改為新版odbc 的連接語法, 例如 ACE.15.0
2. 在x64上原 report 要執行兩個原廠的 x64 patch .
3. x64上的權限關係, 存放 資料庫的資料夾, 記得要開放權限. , 否則會連不上.