Because the OS can just help, applications get it wrong and users get it wronger
(notice: this answer is mostly windows-focused, although the general concepts apply to most GUI systems)
The key is that UI operations are just "regular" operations run by the code of the program.
All the UI actions done in response to some event (window repaint, widgets response to clicks, ...) boil down to a loop that asks messages from the operating system and dispatches them to the correct procedure. Both the message pump, most of the plumbing and the UI code run in the same userland thread, which is commonly called the UI thread (actually you can have multiple UI threads in some cases, but it's a mess and I've never seen anyone doing that for real).
Thus, if a process is hogging the CPU, it can happen that the other processes never get a chance to run, so the message pumps remain blocked and UIs become unresponsive.
So, usually the whole thing depends from process/thread scheduling; kernel architects have produced tons of scheduling algorithms (Linux is often said to have the "scheduler of the week" ), some favoring UI responsiveness; Windows in particular gives a priority boost to the thread of the current active window, and have a switch to favor interactive use or server use (it mostly governs the length of assigned CPU time slices).
Nonetheless, no algorithm is perfect, especially since they strive to find a balance between system responsiveness and allowing CPU-demanding applications to do their job.
Also, there are often problems with novice programmers who have fundamental misunderstandings of about how the message pump machinery works. A typical case is when you ask to some program to do something and its GUI hangs until the operation terminates; here some programmer decided to run a lengthy operation inside a message handler, blocking the message pump and thus the whole GUI of the application.
Another problem comes from "power users": often messing with processes/threads priority can have tragical results: setting CPU-intensive operations to "high priority" ("yay it'll run faster!") results in rarer scheduling of regular priority threads, and thus to GUI slowdown/hang.
Thus, to summarize:
- UI slowdown is normally a matter of bad CPU scheduling;
- it's difficult for the system to let just the UI run since it's governed by the various message pumps, so you can't just "let the widgets be responsive" - either you let the whole UI thread run (which may do lots of other stuff), or you don't.
- to keep a responsive UI applications must be smart and keep the main thread just for UI, and delegate CPU-intensive or blocking tasks to low priority threads, so that when the CPU is scarce most of the CPU time available will go to keeping the UI going;
- users that mess with process priorities without knowing what they are doing deserve what they get (especially idiots that put heavy processes to "real-time priority", which is even above system-critical processes; almost always the situation ends in forced reboots); on a system that must remain responsive heavy processes must have low priority, the UI will keep going and the heavy process will still get 100% CPU if there isn't other work to do.